CF558E - A Simple Task线段树
给出一个小写字母组成的字符串,然后q个操作,a,b,c ,c为0 ,将区间 [a,b] 按逆字典序排,c为1,将此区间按字典序排。用一颗线段树,维护每个节点各个字母出现的种类数,每次操作操作后,暴力将字母a组成的区间,字母b组成的区间等等,区间内所有元素更新为a,b,等等。打个lazy标记,区间更新搞下就行了。
#pragma comment(linker,"/STACK:102400000,102400000") #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<cstring> #include<set> using namespace std; typedef long long LL; const int mod = 1000000007; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const int maxn = 1e5 + 20; int ch[maxn<<2][30]; int color[maxn << 2]; char str[maxn]; void up(int rt) { for (int i = 0; i < 26; i++) { ch[rt][i] = ch[rt << 1][i] + ch[rt << 1 | 1][i]; } } void down(int l, int r, int rt) { if (color[rt] == -1) return; int mid = (l + r) >> 1; for (int i = 0; i < 26; i++) ch[rt << 1][i] = 0, ch[rt << 1 | 1][i] = 0; ch[rt << 1][color[rt]] = (mid - l + 1); ch[rt << 1 | 1][color[rt]] = r - mid; color[rt << 1] = color[rt << 1 | 1] = color[rt]; color[rt] = -1; } void build(int l, int r, int rt) { color[rt] = -1; if (l == r) { int t = str[l] - 'a'; ch[rt][t]++; return; } int mid = (l + r) >> 1; build(lson); build(rson); up(rt); } int ask(int L, int R, int add, int l, int r, int rt) { if (L <= l&&r <= R) { return ch[rt][add]; } int mid = (l + r) >> 1; int ans = 0; down(l, r, rt); if (L <= mid) ans += ask(L, R, add, lson); if (R > mid) ans += ask(L, R, add, rson); return ans; } void update(int L, int R, int add, int l, int r, int rt) { if (L <= l&&r <= R) { for (int i = 0; i < 26; i++) ch[rt][i] = 0; ch[rt][add] = (r - l + 1); color[rt] = add; return; } down(l, r, rt); int mid = (l + r) >> 1; if (L <= mid) update(L, R, add, lson); if (R > mid) update(L, R, add, rson); up(rt); } int ans = 0; void show(int l, int r, int rt) { if (l == r) { for (int i = 0; i < 26; i++) if (ch[rt][i]) printf("%c", i + 'a'); return; } down(l,r,rt); int mid = (l + r) >> 1; show(lson); show(rson); } int cc[100]; int main() { //freopen("1.in", "r", stdin); //freopen("2.in", "w", stdout); int q, n; int a, b, c; cin >> n >> q; scanf("%s", str); build(0, n-1, 1); while (q--) { scanf("%d%d%d", &a, &b, &c); a--; b--; if (c == 1) { for (int i = 0; i < 26; i++) cc[i + 1] = ask(a, b, i, 0, n - 1, 1); int ll = a; for (int i = 0; i < 26; i++) { if (cc[i + 1] == 0) continue; update(ll, ll + cc[i + 1] - 1, i, 0, n - 1, 1); ll = ll + cc[i + 1]; } } else { for (int i = 0; i < 26; i++) cc[i + 1] = ask(a, b, i, 0, n - 1, 1); int ll = a; for (int i = 25; i >= 0; i--) { if (cc[i + 1] == 0) continue; update(ll, ll + cc[i + 1] - 1, i, 0, n - 1, 1); ll = ll + cc[i + 1]; } } } show(0, n - 1, 1); return 0; }