[线段树]JZOJ 5829 string
分析
本来想了一波区间k大还是什么玩意儿然后嘀咕怎么提高组也考这个
结果赛后才看到只有小写字母
那用线段树维护啊,如果区间只有一种字母就标记其他差不多
#include <iostream> #include <cstdio> #include <memory.h> #define l(p) t[p].l #define r(p) t[p].r #define c(p) t[p].c using namespace std; const int N=100001; struct Node { int l,r,c; }t[4*N]; int aoq[26]; char s[N]; int n,m; void Build(int x,int l,int r) { l(x)=l;r(x)=r; if (l==r) { c(x)=s[l]-'a'+1; return; } int mid=l+r>>1; Build(x*2,l,mid);Build(x*2+1,mid+1,r); c(x)=c(x*2)*(c(x*2)==c(x*2+1)); } void Change(int x,int l,int r,int dat) { if (l<=l(x)&&r(x)<=r||c(x)==dat) { c(x)=dat; return; } int mid=l(x)+r(x)>>1; if (c(x)) c(x*2)=c(x*2+1)=c(x),c(x)=0; if (l<=mid) Change(x*2,l,r,dat); if (r>mid) Change(x*2+1,l,r,dat); c(x)=c(x*2)*(c(x*2)==c(x*2+1)); } void Query(int x,int l,int r) { if (l>r(x)||l(x)>r) return; if (l<=l(x)&&r(x)<=r&&c(x)) { aoq[c(x)-1]+=r(x)-l(x)+1; return; } if (c(x)) c(x*2)=c(x*2+1)=c(x); int mid=l(x)+r(x)>>1; if (l<=mid) Query(x*2,l,r); if (r>mid) Query(x*2+1,l,r); } void Pushdown(int x) { if (c(x)) { for (int i=l(x);i<=r(x);i++) s[i]=c(x)+'a'-1; return; } Pushdown(x*2);Pushdown(x*2+1); } int main() { freopen("string.in","r",stdin); freopen("string.out","w",stdout); scanf("%d%d",&n,&m); scanf("%s",s+1); Build(1,1,n); while (m--) { int l,r,c; scanf("%d%d%d",&l,&r,&c); memset(aoq,0,sizeof aoq); Query(1,l,r); if (c) { int ll=l; for (int i=0;i<26;i++) if (aoq[i]) Change(1,ll,ll+aoq[i]-1,i+1),ll+=aoq[i]; } else { int ll=l; for (int i=25;i>=0;i--) if (aoq[i]) Change(1,ll,ll+aoq[i]-1,i+1),ll+=aoq[i]; } } Pushdown(1); for (int i=1;i<=n;i++) printf("%c",s[i]); fclose(stdin);fclose(stdout); }
在日渐沉没的世界里,我发现了你。