JZOJ P5829 string 线段树
*题意:2个操作,1:[l,r]升序排序,2:[l,r]降序排序,最后输出序列
*线段树维护:[l,r]区间的字母是什么(必须完全覆盖),这样我们求字母个数的时候就等于(r-l+1)
*和普通线段树的区别:
1.建树的pushup:当左区间和右区间都是同一个字母,当前区间也是同一个字母
il int rs(int x){return x<<1|1;}
il void pushup(int x){
if (tree[ls(x)].num==tree[rs(x)].num) tree[x].num=tree[ls(x)].num;
}
2.修改和查询的pushdown:下传之后因为排序,字母不在原来的位置,所以要清零
il void pushdown(int x){
if (tree[x].num) tree[ls(x)].num=tree[x].num,tree[rs(x)].num=tree[x].num,tree[x].num=0;
}
最后输出的时候我们查询[i,i]这个单位区间,哪个字母的个数为1,就输出,记得清零
完整代码,会线段树的看代码应该会更清晰:
1 #include <iostream>
2 #include <algorithm>
3 #include <cstdio>
4 #include <cstring>
5 #define il inline
6 using namespace std;
7 const int maxn=1e6;
8 int n,m,l,r,mark,f[30];
9 char a[maxn];
10 struct node{
11 int num;
12 }tree[4*maxn];
13 il int ls(int x){return x<<1;}
14 il int rs(int x){return x<<1|1;}
15 il void pushup(int x){
16 if (tree[ls(x)].num==tree[rs(x)].num) tree[x].num=tree[ls(x)].num;
17 }
18 il void build(int x,int l,int r){
19 if (l==r){int pos=a[l]-'a'+1;tree[x].num=pos;return;}
20 int mid=(l+r)>>1;
21 build(ls(x),l,mid); build(rs(x),mid+1,r);
22 pushup(x);
23 }
24 il void pushdown(int x){
25 if (tree[x].num) tree[ls(x)].num=tree[x].num,tree[rs(x)].num=tree[x].num,tree[x].num=0;
26 }
27 il void query(int x,int l,int r,int nl,int nr){
28 if (nl<=l&&r<=nr&&tree[x].num!=0){f[tree[x].num]+=l-r+1;return;}
29 int mid=(l+r)>>1;
30 pushdown(x);
31 if (nl<=mid) query(ls(x),l,mid,nl,nr);
32 if (nr>mid) query(rs(x),mid+1,r,nl,nr);
33 }
34 il void update(int x,int l,int r,int nl,int nr,int i){
35 // cout<<1<<endl;
36 if (nl<=l&&r<=nr||tree[x].num==i){tree[x].num=i;return;}
37 int mid=(l+r)>>1;
38 pushdown(x);
39 if (nl<=mid) update(ls(x),l,mid,nl,nr,i);
40 if (nr>mid) update(rs(x),mid+1,r,nl,nr,i);
41 pushup(x);
42 }
43 int main(){
44 scanf ("%d%d",&n,&m);
45 getchar();
46 for (int i = 1;i <= n;i++) scanf ("%c",&a[i]);
47 build(1,1,n);
48 for (int i = 1;i <= m;i++){
49 memset(f,0,sizeof(f));
50 scanf ("%d%d%d",&l,&r,&mark);
51 query(1,1,n,l,r);
52 if (mark){
53 for (int i = 1;i <= 26;i++){
54 if (f[i]) update(1,1,n,l,l+f[i]-1,i),l=l+f[i];
55 }
56 }
57 else {
58 for (int i = 26;i >= 1;i--){
59 if (f[i]) update(1,1,n,l,l+f[i]-1,i),l=l+f[i];
60 }
61 }
62 }
63 for (int i = 1;i <= n;i++){
64 for (int j = 1;j <= 26;j++){
65 memset(f,0,sizeof(f));
66 query(1,1,n,i,i);
67 if (f[j]){char tmp='a'+j-1;cout<<tmp;break;}
68 }
69 }
70 return 0;
71
72 }