[线段树] Jzoj P5829 string

Description

给定一个由小写字母组成的字符串 s。有 m 次操作,每次操作给 定 3 个参数 l,r,x。如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r] 降序排序。你需要求出最终序列。 
 

Input

第一行两个整数 n,m。第二行一个字符串 s。接下来 m 行每行三 个整数 l,r,x。

Output

一行一个字符串表示答案。 
 

Sample Input

5 2
cabcd
1 3 1
3 5 0 

Sample Output

abdcc
 

Data Constraint

对于 40%的数据,n,m<=1000。
对于 100%的数据,n,m<=100000

题解

  • 可以建一棵线段树
  • 把各个叶子节点就是对应字母的值
  • 然后对于一个节点,如果其两个子节点的数值相同,那么它自己也附上相同的值
  • 更改时如果区间不完全重合,那么就需要把其子孩子附上它的值
  • 然后对于每一次操作,求其区间内各个字母的次数
  • 然后按照要求从a-z或从z-a循环,依次替换线段树中的位置

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 struct edge{int l,r,v;}tree[400010];
 7 char s[100010];
 8 int n,m,f[30];
 9 void build(int l,int r,int d)
10 {
11     tree[d].l=l,tree[d].r=r;
12     if (l==r)
13     {
14         tree[d].v=s[l]-'a'+1;
15         return;
16     }
17     int mid=(l+r)/2;
18     build(l,mid,d*2),build(mid+1,r,d*2+1);
19     if (tree[d*2].v==tree[d*2+1].v) tree[d].v=tree[d*2].v;
20 }
21 void getnum(int l,int r,int d)
22 {
23     if (tree[d].l>=l&&tree[d].r<=r&&tree[d].v!=0)
24     {
25         f[tree[d].v]+=tree[d].r-tree[d].l+1;
26         return;
27     }
28     if (tree[d].v) tree[d*2].v=tree[d].v,tree[d*2+1].v=tree[d].v;
29     int mid=(tree[d].l+tree[d].r)/2;
30     if (mid>=l) getnum(l,r,d*2);
31     if (mid<r) getnum(l,r,d*2+1);
32 }
33 void change(int l,int r,int d,int x)
34 {
35     if (tree[d].l>=l&&tree[d].r<=r||tree[d].v==x)
36     {
37         tree[d].v=x;
38         return;
39     }
40     if (tree[d].v) tree[d*2].v=tree[d].v,tree[d*2+1].v=tree[d].v,tree[d].v=0;
41     int mid=(tree[d].l+tree[d].r)/2;
42     if (l<=mid) change(l,r,d*2,x);
43     if (mid<r) change(l,r,d*2+1,x);
44     if (tree[d*2].v==tree[d*2+1].v) tree[d].v=tree[d*2].v;
45 }
46 void out(int d)
47 {
48     if (tree[d].v)
49     {
50         for (int i=1;i<=tree[d].r-tree[d].l+1;i++) printf("%c",tree[d].v+'a'-1);
51         return;
52     }
53     out(d*2),out(d*2+1);
54 }
55 int main()
56 {
57     freopen("string.in","r",stdin);
58     freopen("string.out","w",stdout);
59     scanf("%d%d",&n,&m);
60     scanf("%s",s+1);
61     build(1,n,1);
62     for (int j=1;j<=m;j++)
63     {
64         int l,r,x;
65         scanf("%d%d%d",&l,&r,&x);
66         memset(f,0,sizeof(f));
67         getnum(l,r,1);
68         if (x==1)
69             for (int i=1;i<=26;i++)
70             {
71                 if (f[i]) change(l,l+f[i]-1,1,i),l=l+f[i];
72             }
73         else 
74             for (int i=26;i>=1;i--)
75             {
76                 if (f[i]) change(l,l+f[i]-1,1,i),l=l+f[i];
77             }
78     }
79     out(1);
80     return 0;
81 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9498326.html
今日推荐