[CF558E] A Simple Task

18.10.16模拟赛T3。

我当场切掉的。

CF传送门

洛谷传送门

考试的时候数据范围是1~7。

思路都差不多。

发现排成有序之后,肯定是一段1,一段2......最后是一段26(以升序为例)。

这实际上是一个桶排的过程。

我们用线段树维护每个数出现的次数。

每次修改的时候,先统计区间里每种数都有多少个。

这样就可以确定排序之后每段的左右端点了。

最后用线段树的区间修改进行赋值。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 
  6 int n,q;
  7 char s[100005];
  8 int h[400005][30];
  9 int lb[400005],rb[400005],fl[400005];
 10 int qt[30];
 11 
 12 void pushup(int p)
 13 {
 14     for(int i=1;i<=26;i++)
 15         h[p][i]=h[p<<1][i]+h[p<<1|1][i];
 16 }
 17 
 18 void pushdown(int p)
 19 {
 20     if(!fl[p])return;
 21     for(int i=1;i<=26;i++)
 22         h[p<<1][i]=h[p<<1|1][i]=0;
 23     h[p<<1][fl[p]]=rb[p<<1]-lb[p<<1]+1;
 24     h[p<<1|1][fl[p]]=rb[p<<1|1]-lb[p<<1|1]+1;
 25     fl[p<<1]=fl[p];
 26     fl[p<<1|1]=fl[p];
 27     fl[p]=0;
 28 }
 29 
 30 void build(int p,int l,int r)
 31 {
 32     lb[p]=l,rb[p]=r;
 33     if(l==r)
 34     {
 35         h[p][s[l]-'a'+1]=1;
 36         return;
 37     }
 38     int mid=(l+r)>>1;
 39     build(p<<1,l,mid);
 40     build(p<<1|1,mid+1,r);
 41     pushup(p);
 42 }
 43 
 44 void cnt(int p,int l,int r)
 45 {
 46     if(l<=lb[p]&&r>=rb[p])
 47     {
 48         for(int i=1;i<=26;i++)
 49             qt[i]+=h[p][i];
 50         return;
 51     }
 52     pushdown(p);
 53     int mid=(lb[p]+rb[p])>>1;
 54     if(l<=mid)cnt(p<<1,l,r);
 55     if(r>mid)cnt(p<<1|1,l,r);
 56 }
 57 
 58 void change(int p,int l,int r,int v)
 59 {
 60     if(l<=lb[p]&&r>=rb[p])
 61     {
 62         fl[p]=v;
 63         for(int i=1;i<=26;i++)h[p][i]=0;
 64         h[p][v]=rb[p]-lb[p]+1;
 65         return;
 66     }
 67     pushdown(p);
 68     int mid=(lb[p]+rb[p])>>1;
 69     if(l<=mid)change(p<<1,l,r,v);
 70     if(r>mid)change(p<<1|1,l,r,v);
 71     pushup(p);
 72 }
 73 
 74 int res[100005];
 75 
 76 void get(int p)
 77 {
 78     if(fl[p])
 79     {
 80         for(int i=lb[p];i<=rb[p];i++)
 81             res[i]=fl[p];
 82         return;
 83     }
 84     if(lb[p]==rb[p])
 85     {
 86         int wh=0;
 87         for(int i=1;i<=26;i++)
 88         {
 89             if(h[p][i])
 90             {
 91                 wh=i;
 92                 break;
 93             }
 94         }
 95         res[lb[p]]=wh;
 96         return;
 97     }
 98     get(p<<1);
 99     get(p<<1|1);
100 }
101 
102 int main()
103 {
104     scanf("%d%d",&n,&q);
105     scanf("%s",s+1);
106     build(1,1,n);
107     for(int i=1;i<=q;i++)
108     {
109         int l,r,op;
110         scanf("%d%d%d",&l,&r,&op);
111         if(l>r)swap(l,r);
112         if(l==r)continue;
113         for(int j=1;j<=26;j++)qt[j]=0;
114         cnt(1,l,r);
115         int np=l;
116         if(op==1)
117         {
118             for(int j=1;j<=26;j++)
119             {
120                 if(qt[j])change(1,np,np+qt[j]-1,j);
121                 np=np+qt[j];
122             }
123         }else
124         {
125             for(int j=26;j;j--)
126             {
127                 if(qt[j])change(1,np,np+qt[j]-1,j);
128                 np=np+qt[j];
129             }
130         }
131     }
132     get(1);
133     for(int i=1;i<=n;i++)printf("%c",res[i]-1+'a');
134     return 0;
135 }

 

posted @ 2018-10-17 13:46  cervusky  阅读(268)  评论(0编辑  收藏  举报

Contact with me