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("\n"); 139 } 140 141 void work() 142 { 143 int ll, rr, opt; 144 for(R i = 1; i <= m; i ++) 145 { 146 // printf("%d\n", 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("\n"); 180 } 181 182 int main() 183 { 184 //freopen("string6.in", "r", stdin); 185 pre(); 186 work(); 187 //fclose(stdin); 188 return 0; 189 }