线段树维护桶排序

类似于​​【HEOI2016】排序​​。

可以用线段树维护 \(0/1\) 序列,同样也可以维护 \(26\) 个字母或者有限个数字(合理外推的结果)。

代码非原创。

#include<bits/stdc++.h>
#define re register
using namespace std;
char a[100010];
int f[27],n,m;
struct zxb
{int l,r,ji;}tree[400010];
namespace AYX
{ inline void pushup(int x){if(tree[x<<1].ji==tree[x<<1|1].ji)tree[x].ji=tree[x<<1].ji;}
inline void pushdown(int x){if(tree[x].ji)tree[x<<1].ji=tree[x<<1|1].ji=tree[x].ji;tree[x].ji=0;}
inline void build(int x,int l,int r)
{ if(l==r)
{ tree[x].ji=a[l]-'a'+1;
return;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
inline void query(int x,int l,int r,int L,int R)
{ if(l>=L and r<=R and tree[x].ji)
{f[tree[x].ji]+=r-l+1;return;}
pushdown(x);
int mid=(l+r)>>1;
if(mid>=L)query(x<<1,l,mid,L,R);
if(mid<R)query(x<<1|1,mid+1,r,L,R);
}
inline void update(int x,int l,int r,int L,int R,int j)
{ if(l>=L and r<=R){tree[x].ji=j;return;}
pushdown(x);
int mid=(l+r)>>1;
if(mid<R)update(x<<1|1,mid+1,r,L,R,j);
if(mid>=L)update(x<<1,l,mid,L,R,j);
}
inline void p(int x,int l,int r)
{ if(tree[x].ji){for(int i=l;i<=r;++i)putchar(tree[x].ji+'a'-1);return;}
int mid=(l+r)>>1;
p(x<<1,l,mid);
p(x<<1|1,mid+1,r);
}
inline short main()
{ //freopen("c.in","r",stdin);
scanf("%d%d",&n,&m);
scanf("%s",a+1);
build(1,1,n);
while(m--)
{ int l,r,opt,sum=0;
scanf("%d%d%d",&l,&r,&opt);
memset(f,0,sizeof(f));
query(1,1,n,l,r);sum=l;
if(opt==1)
{
for(int i=1;i<=26;++i)
if(f[i])update(1,1,n,sum,sum+f[i]-1,i),sum+=f[i];
}
else
{ for(int i=26;i;--i)
if(f[i])update(1,1,n,sum,sum+f[i]-1,i),sum+=f[i];
}
}
p(1,1,n);
}
}
signed main()
{return AYX::main();}