CF#312 558e A Simple Task

~~~题面~~~

题解:

  观察到字母只有26个,因此考虑对这26个字母分别维护,每个线段树维护一个字母,如果一个线段树的某个叶节点有值,表示当前叶节点所在位置的字母是现在这个线段树代表的字母。

  那么对于每一个操作,我们已经知道最后排好序之后肯定是按aaaabbbbccccddd……这样的序列排下去的(有些字母可能没有),每个字母都集中在自己的区间内。

  那么我们只需要知道每个字母之前的字母有多少个,就可以知道这个字母所在区间,因此按顺序修改。

  (以下操作均视为在每个字母对应的线段树上操作)先查询a的个数,并把当前修改的区间内赋0,然后把前1~tot_a全都赋1,表示这段区间是属于a的(全都放上1)。

  记在统计当前字母之前找到的字母个数之和为tot,则每次都是把当前线段树管理的字母全都移动到tot + 1~tot + 字母个数,相当于跟修改a类似的区间操作。只不过属于这个字母的区间的开始端点是tot + 1(其实a的情况也可以视作是tot + 1,因为这个时候tot = 0)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define R register int
  4 #define LL long long
  5 #define AC 101000
  6 #define ac 401000
  7 
  8 int n, m, id, tot, add, t;
  9 int l[ac], r[ac];
 10 char s[AC], ans[AC];
 11 
 12 int read()
 13 {
 14     int x = 0;char c = getchar();
 15     while(c > '9' || c < '0') c = getchar();
 16     while(c >= '0' && c <= '9') x = x * 10 + c -'0', c = getchar();
 17     return x;
 18 }
 19 
 20 inline void upmin(int &a, int b)
 21 {
 22     if(b < a) a = b;
 23 }
 24 
 25 inline void upmax(int &a, int b)
 26 {
 27     if(b > a) a = b;
 28 }
 29 
 30 struct segament_tree{
 31     int tree[ac], lazy[ac], id;
 32     
 33     inline void init()
 34     {
 35         memset(lazy, -1, sizeof(lazy));
 36     }
 37     
 38     inline void update(int x)
 39     {
 40         tree[x] = tree[x * 2] + tree[x * 2 + 1];
 41     }
 42     
 43     inline void pushdown(int x)
 44     {
 45         if(lazy[x] != -1)
 46         {
 47             int ll = x * 2, rr = ll + 1;
 48             lazy[ll] = lazy[rr] = lazy[x];
 49             if(!lazy[x]) tree[ll] = tree[rr] = 0;
 50             else
 51             {
 52                 int mid = (l[x] + r[x]) >> 1;
 53                 tree[ll] = mid - l[ll] + 1;
 54                 tree[rr] = r[rr] - mid;
 55             }
 56             lazy[x] = -1;
 57         }
 58     }
 59     
 60     void build(int x, int ll, int rr)
 61     {
 62         if(!id) l[x] = ll, r[x] = rr;
 63         if(ll == rr) 
 64         {
 65             if(s[ll] == id + 'a') tree[x] = 1;
 66             return ;
 67         }
 68         int mid = (ll + rr) >> 1;
 69         build(x * 2, ll, mid);
 70         build(x * 2 + 1, mid + 1, rr);
 71         update(x);
 72     }
 73     
 74     void find(int x, int ll, int rr)
 75     {
 76         if(!tree[x]) return ;
 77         if(l[x] == ll && r[x] == rr){add += tree[x]; return ;}
 78         pushdown(x);
 79         int mid = (l[x] + r[x]) >> 1;
 80         if(rr <= mid) find(x * 2, ll, rr);
 81         else if(ll > mid) find(x * 2 + 1, ll, rr);
 82         else
 83         {
 84             find(x * 2, ll, mid);
 85             find(x * 2 + 1, mid + 1, rr);
 86         }
 87         update(x);
 88     }
 89     
 90     void change(int x, int ll, int rr)
 91     {
 92         if(l[x] == ll && r[x] == rr)
 93         {
 94             lazy[x] = t;
 95             if(t) tree[x] = rr - ll + 1;
 96             else tree[x] = 0;
 97             return ;
 98         }    
 99         pushdown(x);
100         int mid = (l[x] + r[x]) >> 1;
101         if(rr <= mid) change(x * 2, ll, rr);
102         else if(ll > mid) change(x * 2 + 1, ll, rr);
103         else
104         {
105             change(x * 2, ll, mid);
106             change(x * 2 + 1, mid + 1, rr);
107         }
108         update(x);
109     }
110 
111     void get(int x)
112     {
113         if(!tree[x]) return ;
114         if(tree[x] == r[x] - l[x] + 1)
115         {
116             for(R i = l[x]; i <= r[x]; i ++) ans[i] = id + 'a';
117             return ;
118         }
119         pushdown(x);
120         if(tree[x * 2]) get(x * 2);
121         if(tree[x * 2 + 1]) get(x * 2 + 1);
122     }
123 
124 }T[26];
125 
126 void pre()
127 {
128     n = read(), m = read();
129     scanf("%s", s + 1);
130     for(R i = 0; i < 26; i ++) 
131         T[i].id = i, T[i].init(), T[i].build(1, 1, n);
132 }
133 
134 void check()
135 {
136     for(R i = 0; i < 26; i ++) T[i].get(1);
137     for(R i = 1; i <= n; i ++) printf("%c", ans[i]);
138     printf("
");
139 }
140 
141 void work()
142 {
143     int ll, rr, opt;
144     for(R i = 1; i <= m; i ++)
145     {
146     //    printf("%d
", i);
147         ll = read(), rr = read(), opt = read(), tot = ll - 1;
148         if(opt)
149         {
150             for(R j = 0; j < 26; j ++)
151             {
152                 add = t = 0;
153                 T[j].find(1, ll, rr);
154                 if(!add) continue;
155                 T[j].change(1, ll, rr);
156                 t = 1;
157                 T[j].change(1, tot + 1, tot + add);
158                 tot += add;
159             }
160             //check();
161         }
162         else
163         {
164             for(R j = 25; j >= 0; j --)
165             {
166                 add = t = 0;
167                 T[j].find(1, ll, rr);
168                 if(!add) continue;
169                 T[j].change(1, ll, rr);
170                 t = 1;
171                 T[j].change(1, tot + 1, tot + add);
172                 tot += add;
173             }
174         //    check();
175         }
176     }
177     for(R i = 0; i < 26; i ++) T[i].get(1);
178     for(R i = 1; i <= n; i ++) printf("%c", ans[i]);
179     printf("
");
180 }
181 
182 int main()
183 {
184     //freopen("string6.in", "r", stdin);
185     pre();
186     work();
187     //fclose(stdin);
188     return 0;
189 }
View Code
原文地址:https://www.cnblogs.com/ww3113306/p/9847478.html