zoukankan      html  css  js  c++  java
  • CF558E A Simple Task

    题目大意

      给定一个长度不超过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, &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("
    ");
        return 0;
    }
    

      

  • 相关阅读:
    把arguments转化成数组
    最小化重绘和重排
    选择器API
    事件委托
    WAhaha_hnu (zoj 2010 oct月赛)
    素数计数公式全面拉丁化改写小有改进Meissel公式梅塞尔Lehmer公式莱梅=勒梅尔筛法三种形式孟庆余公式(转载)
    NBUT 2013 Timed NOJ Training #005
    2013 腾讯马拉松初赛第一场
    hrboj 1683 树形DP
    哈尔滨2013校赛训练赛 4 解题思路
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9427022.html
Copyright © 2011-2022 走看看