1. 程式人生 > >CF558E A Simple Task

CF558E A Simple Task

main private 範圍 字符串排序 prev turn ace mem amp

題目大意

  給定一個長度不超過10^5的字符串(小寫英文字母),和不超過5000個操作。每個操作 L R K 表示給區間[L,R]的字符串排序,K=1為升序,K=0為降序。最後輸出最終的字符串。

題解

  我們做過luogu2828,那裏我們無法對一段數字序列進行具體排序,那麽這道題我們就要考慮其獨有的特點。字母只有26個!所以我們對每個字母維護一個key值為下標,值為在下標範圍內該字母出現次數的權值線段樹即可,修改查詢都很方便。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX_N = 100010, MAX_ALPHA = 30;
int N;
int OrgData[MAX_N];
int ValPosCnt[MAX_ALPHA][MAX_N];

struct RangeTree
{
private:
    static const int MAX_NODE = MAX_N * 4;
    int Sum[MAX_NODE], Cover[MAX_NODE];
    
    void PushDown(int cur, int l, int r)
    {
        if(Cover[cur] != -1)
        {
            Cover[cur * 2] = Cover[cur * 2 + 1] = Cover[cur];
            int mid = (l + r) / 2;
            Sum[cur * 2] = (mid - l + 1) * Cover[cur];
            Sum[cur * 2 + 1] = (r - mid) * Cover[cur];
            Cover[cur] = -1;
        }
    }
    
    void PullUp(int cur)
    {
        Sum[cur] = Sum[cur * 2] + Sum[cur * 2 + 1];
    }
    
    void Init(int cur, int l, int r, int *a)
    {
        if(l == r)
        {
            Sum[cur] = a[l];
            return;
        }
        int mid = (l + r) / 2;
        Init(cur * 2, l, mid, a);
        Init(cur * 2 + 1, mid + 1, r, a);
        PullUp(cur);
    }
    
    int Query_Update(int cur, int curL, int curR, int askL, int askR, int cover)
    {
        if(askL <= curL && curR <= askR)
        {
            int ans = Sum[cur];
            Sum[cur] = (curR - curL + 1) * cover;
            Cover[cur] = cover;
            return ans;
        }
        PushDown(cur, curL, curR);
        int mid = (curL + curR) / 2, ans = 0;
        if(askL <= mid)
            ans += Query_Update(cur * 2, curL, mid, askL, askR, cover);
        if (askR > mid)
            ans += Query_Update(cur * 2 + 1, mid + 1, curR, askL, askR, cover);
        PullUp(cur);
        return ans;
    }
    
    void OutPut(int cur, int l, int r, int *a, int val)
    {
        if(Sum[cur] == r - l + 1)
        {
            for (int i = l; i <= r; i++)
                a[i] = val;
            return;
        }
        PushDown(cur, l, r);
        int mid = (l + r) / 2;
        if(Sum[cur * 2])
            OutPut(cur * 2, l, mid, a, val);
        if (Sum[cur * 2 + 1])
            OutPut(cur * 2 + 1, mid + 1, r, a, val); 
    }
    
public:
    RangeTree()
    {
        memset(Cover, -1, sizeof(Cover));
    }
    
    void Init(int *a)
    {
        Init(1, 1, N, a);
    }
    
    int Query_Update(int l, int r, int cover)
    {
        return Query_Update(1, 1, N, l, r, cover);
    }
    
    void OutPut(int *a, int val)
    {
        OutPut(1, 1, N, a, val);
    }
}g[MAX_ALPHA];

int main()
{
    int opCnt;
    scanf("%d%d\n", &N, &opCnt);
    for (int i = 1; i <= N; i++)
    {
        char c;
        scanf("%c", &c);
        OrgData[i] = c - ‘a‘ + 1;
    }
    for (int i = 1; i <= N; i++)
        ValPosCnt[OrgData[i]][i] += 1;
    for (int i = 1; i <= 26; i++)
        g[i].Init(ValPosCnt[i]);
    while(opCnt--)
    {
        int l, r, op;
        scanf("%d%d%d", &l, &r, &op);
        switch(op)
        {
            int prevR, prevL, num;
        case 1:
            prevR = l - 1;
            for (int i = 1; i <= 26; i++)
            {
                num = g[i].Query_Update(l, r, 0);
                if (num)
                {
                    g[i].Query_Update(prevR + 1, prevR + num, 1);
                    prevR = prevR + num;
                }
            }
            break;
        case 0:
            prevL = r + 1;
            for (int i = 1; i <= 26; i++)
            {
                num = g[i].Query_Update(l, r, 0);
                if (num)
                {
                    g[i].Query_Update(prevL - num, prevL - 1, 1);
                    prevL = prevL - num;
                }
            }
            break;
        }
    }
    static int ans[MAX_N];
    memset(ans, 0, sizeof(ans));
    for (int i = 1; i <= 26; i++)
        g[i].OutPut(ans, i);
    for (int i = 1; i <= N; i++)
        printf("%c", ans[i] + ‘a‘ - 1);
    printf("\n");
    return 0;
}

  

CF558E A Simple Task