题目:http://codeforces.com/contest/558/problem/E
题意:给你一个字符串s,|s|<=1e5。有q(q<50 000)次操作,有2种操作类型。①将给定区间的字符按非降序排序②将给定区间的字符按非升序排序。
分析:
计数排序:先统计区间内每种字符的个数,然后按顺序将字符分配。
例如bccasabdass
a有3个 b有2个 c有2个 d有1个 s有3个
按顺序分配之后就是aaabbccdsss,就已经排好序了。
现在用线段树的每个节点保存区间内每种字符的个数,如果操作将一段区间变为升序的话,先统计区间各字符的个数,然后按顺序分配给线段树中的合法区间,并且和以前一样用懒惰标记方法处理区间更新。
代码:
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 1E9+9;
const int maxn = 1e5+6;
char str[maxn];
struct node
{
int num[26];
int lazy;
}tree[maxn<<2];
int n,q;
void pushdown(int l,int r,int rt)
{
if(tree[rt].lazy==1) //increasing
{
memset(tree[rt<<1].num,0,sizeof(int)*26);
memset(tree[rt<<1|1].num,0,sizeof(int)*26);
int m=(l+r)>>1;
int rangeL=m-l+1;
int cnt=0,i;
for(i=0;i<26;i++)
{
if(cnt+tree[rt].num[i]>=rangeL)
{
tree[rt<<1].num[i]=rangeL-cnt;
tree[rt<<1|1].num[i]=tree[rt].num[i]-(rangeL-cnt);
i++;
break;
}
cnt+=tree[rt].num[i];
tree[rt<<1].num[i]=tree[rt].num[i];
}
for(;i<26;i++)
tree[rt<<1|1].num[i]=tree[rt].num[i];
// printf("[%d %d] [%d %d]\n",l,m,m+1,r);
// for(int i=0;i<26;i++)
// {
// int t=tree[rt<<1].num[i];
// while(t--)
// putchar('a'+i);
// }
// printf("|");
// for(int i=0;i<26;i++)
// {
// int t=tree[rt<<1|1].num[i];
// while(t--)
// putchar('a'+i);
// }
// printf("\n");
tree[rt<<1].lazy=tree[rt<<1|1].lazy=1;
tree[rt].lazy=-1;
}
else if(tree[rt].lazy==0) //decreasing
{
memset(tree[rt<<1].num,0,sizeof(int)*26);
memset(tree[rt<<1|1].num,0,sizeof(int)*26);
int m=(l+r)>>1;
int rangeL=m-l+1;
int cnt=0,i;
for(i=25;i>=0;i--)
{
if(cnt+tree[rt].num[i]>=rangeL)
{
tree[rt<<1].num[i]=rangeL-cnt;
tree[rt<<1|1].num[i]=tree[rt].num[i]-(rangeL-cnt);
i--;
break;
}
cnt+=tree[rt].num[i];
tree[rt<<1].num[i]=tree[rt].num[i];
}
for(;i>=0;i--)
tree[rt<<1|1].num[i]=tree[rt].num[i];
tree[rt<<1].lazy=tree[rt<<1|1].lazy=0;
tree[rt].lazy=-1;
}
return ;
}
void pushup(int rt)
{
for(int i=0;i<26;i++)
tree[rt].num[i]=tree[rt<<1].num[i]+tree[rt<<1|1].num[i];
}
void build(int pos,char ch,int l,int r,int rt)
{
tree[rt].lazy=-1;
if(l==r)
{
memset(tree[rt].num,0,sizeof(int)*26);
tree[rt].num[ch-'a']++;
return ;
}
int m=(l+r)>>1;
if(pos<=m)
build(pos,ch,lson);
else
build(pos,ch,rson);
pushup(rt);
}
int buf[26];
void query(int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R)
{
for(int i=0;i<26;i++)
buf[i]+=tree[rt].num[i];
return ;
}
pushdown(l,r,rt);
int m=(l+r)>>1;
if(L<=m)
query(L,R,lson);
if(R>m)
query(L,R,rson);
pushup(rt);
}
void Q(int L,int R)
{
memset(buf,0,sizeof(buf));
query(L,R,1,n,1);
}
void update1(int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R)
{
int range=r-l+1,cnt=0;
memset(tree[rt].num,0,sizeof(int)*26);
for(int i=0;i<26;i++)
{
if(cnt+buf[i]>=range)
{
tree[rt].num[i]+=range-cnt;
buf[i]-=(range-cnt);
break;
}
tree[rt].num[i]=buf[i];
cnt+=buf[i];
buf[i]=0;
}
tree[rt].lazy=1;
return ;
}
pushdown(l,r,rt);
int m=(l+r)>>1;
if(L<=m)
update1(L,R,lson);
if(R>m)
update1(L,R,rson);
pushup(rt);
}
void update0(int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R)
{
int range=r-l+1,cnt=0;
memset(tree[rt].num,0,sizeof(int)*26);
for(int i=25;i>=0;i--)
{
if(cnt+buf[i]>=range)
{
tree[rt].num[i]+=range-cnt;
buf[i]-=(range-cnt);
break;
}
tree[rt].num[i]=buf[i];
cnt+=buf[i];
buf[i]=0;
}
tree[rt].lazy=0;
return ;
}
pushdown(l,r,rt);
int m=(l+r)>>1;
if(L<=m)
update0(L,R,lson);
if(R>m)
update0(L,R,rson);
pushup(rt);
}
char getChar(int pos,int l,int r,int rt)
{
if(l==r)
{
for(int i=0;i<26;i++)
if(tree[rt].num[i])
return 'a'+i;
return '*';
}
pushdown(l,r,rt);
int m=(l+r)>>1;
if(pos<=m)
return getChar(pos,lson);
else
return getChar(pos,rson);
pushup(rt);
}
int main()
{
int i,j,k;
scanf("%d%d",&n,&q);
scanf("%s",str);
for(int i=0;str[i];i++)
build(i+1,str[i],1,n,1);
// for(int i=0;str[i];i++)
// {
// putchar(getChar(i+1,1,n,1));
// }
// printf("\n");
while(q--)
{
scanf("%d%d%d",&i,&j,&k);
Q(i,j);
if(k==1)
update1(i,j,1,n,1);
else
update0(i,j,1,n,1);
// for(int i=0;str[i];i++)
// {
// putchar(getChar(i+1,1,n,1));
// }
// printf("\n");
// int x;
// while(cin>>x)
// {
// putchar(getChar(x,1,n,1));
// }
}
for(int i=1;i<=n;i++)
putchar(getChar(i,1,n,1));
return 0;
}