这个题目的意思是 给你一个由小写字母组成的字符串,有两种操作
i j k 如果k==1 那么就是就把i 到 j 的这个区间非递减排序。
i j k如果k==2 那么就是把 i 到 j 这个区间非递增排序。
n 有 1e5 q(操作次数) 5e4
这个题目不会写,问别人的。
这个要建26棵线段树,首先对这个字符串进行预处理,把每一个位置放到每一个字母放到它的线段树对应的位置。
比如说 acbd a应该放在第一棵树的1位置,c放到第三颗树,2的位置,b放到第二颗树的3号位置,以此类推。
这个是预处理,然后就是对于操作的写法。
每一个操作给你了一个区间,我们先计算这个区间的每一颗线段树的数量的字母数量,然后清空这个区间的每一颗线段树,
再给定区间进行更新。
知道了这些应该可以很好写了。
这种题不知道算不算一种类型,用26棵线段树来解决排序问题,这里是二十六棵线段树,以后可能是建有限个线段树,对他们进行重新排序,
升序或者降序,然后输出结果,都可以借助这种思想。
#include <cstdio> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <vector> #include <algorithm> #include <iostream> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 1e5 + 10; struct node { int sum, lazy, len; }tree[30][maxn*10]; char s[maxn*10]; void push_up(int id) { for(int i=0;i<26;i++) { tree[i][id].sum = tree[i][id << 1].sum + tree[i][id << 1 | 1].sum; } } void build(int id,int l,int r) { for(int i=0;i<26;i++) { tree[i][id].lazy = -1; tree[i][id].len = r - l + 1; } if(l==r) { int x = s[l] - 'a'; tree[x][id].sum = 1; return; } int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); push_up(id); } void push_down(int id) { for(int i=0;i<26;i++) { if(tree[i][id].lazy!=-1) { int val = tree[i][id].lazy; tree[i][id << 1].sum = tree[i][id << 1].len*val; tree[i][id << 1 | 1].sum = tree[i][id << 1 | 1].len*val; tree[i][id << 1].lazy = tree[i][id << 1 | 1].lazy = val; tree[i][id].lazy = -1; } } } int a[50]; void query(int id,int l,int r,int x,int y) { if(x<=l&&y>=r) { for(int i=0;i<26;i++) { a[i] += tree[i][id].sum; } return; } push_down(id); int mid = (l + r) >> 1; if (x <= mid) query(id << 1, l, mid, x, y); if (y > mid) query(id << 1 | 1, mid + 1, r, x, y); } void update(int id,int l,int r,int x,int y)//clear { if(x<=l&&y>=r) { for(int i=0;i<26;i++) { tree[i][id].sum = 0; tree[i][id].lazy = 0; } return; } push_down(id); int mid = (l + r) >> 1; if (x <= mid) update(id << 1, l, mid, x, y); if(y > mid) update(id << 1 | 1, mid + 1, r, x, y); push_up(id); } void updatenum(int id, int l, int r, int x, int y,int ad)//clear { if (x <= l && y >= r) { tree[ad][id].sum = tree[ad][id].len; tree[ad][id].lazy = 1; return; } push_down(id); int mid = (l + r) >> 1; if (x <= mid) updatenum(id << 1, l, mid, x, y, ad); if (y > mid) updatenum(id << 1 | 1, mid + 1, r, x, y, ad); push_up(id); } int main() { int n, m; scanf("%d%d", &n, &m); scanf("%s", s + 1); build(1, 1, n); while(m--) { int l, r, k; scanf("%d%d%d", &l, &r, &k); memset(a, 0, sizeof(a)); query(1, 1, n, l, r); update(1, 1, n, l, r); if(k==0) { for(int i=0;i<26;i++) { if (a[i] == 0) continue; updatenum(1, 1, n, r - a[i] + 1, r, i); r -= a[i]; if (r <= 0) break; } } else if(k==1) { for(int i=0;i<26;i++) { if (a[i] == 0) continue; // printf("i=%d l=%d r=%d ", i, l, l + a[i] - 1); updatenum(1, 1, n, l, l + a[i] - 1, i); l += a[i]; if (l > n) break; } } } for(int i=1;i<=n;i++) { memset(a, 0, sizeof(a)); query(1, 1, n, i, i); for(int j=0;j<26;j++) { if(a[j]) { printf("%c", j + 'a'); } } } printf(" "); return 0; } /* 10 5 hbtngdflmj 1 10 1 2 9 0 3 8 1 4 7 0 5 6 1 */