18.10.16模拟赛T3。
我当场切掉的。
考试的时候数据范围是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 }