【JZOJ A组】 string

Description

给定一个由小写字母组成的字符串 s。有 m 次操作,每次操作给 定 3 个参数 l,r,x。如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r] 降序排序。你需要求出最终序列。

Input

第一行两个整数 n,m。第二行一个字符串 s。接下来 m 行每行三 个整数 l,r,x。

Output

一行一个字符串表示答案。

Sample Input

5 2
cabcd
1 3 1
3 5 0

Sample Output

abdcc

Data Constraint

对于 40%的数据,n,m<=1000。
对于 100%的数据,n,m<=100000

思路

由于只有小写字母,也就说元素只有26种,所以我们考虑用线段树维护区间内有多少字母【a..z】

对于每个修改操作,先统计区间有多少字母,在逐个加入线段树

代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+77;
struct tree
{
    int l,r,v;
}tr[maxn*3];
char st[maxn];
int n,m,f[29];
void build(int l,int r,int x)
{
    tr[x].l=l; tr[x].r=r;
    if(l==r)
    {
        tr[x].v=st[l]-'a'+1; return;
    }
    int mid=(l+r)>>1;
    build(l,mid,x*2); build(mid+1,r,x*2+1);
    if(tr[x*2].v==tr[x*2+1].v) tr[x].v=tr[x*2].v;
}
void get_f(int l,int r,int x)
{
    if(tr[x].l>=l&&tr[x].r<=r&&tr[x].v)
    {
        f[tr[x].v]+=tr[x].r-tr[x].l+1; return;
    }
    if(tr[x].v) tr[x*2].v=tr[x].v,tr[x*2+1].v=tr[x].v;
    int mid=(tr[x].l+tr[x].r)>>1;
    if(mid>=l) get_f(l,r,x*2);
    if(mid<r) get_f(l,r,x*2+1);
}
void work(int l,int r,int u,int x)
{
    if(tr[u].l>=l&&tr[u].r<=r||tr[u].v==x)
    {
        tr[u].v=x; return;
    }
    if(tr[u].v) tr[u*2].v=tr[u].v,tr[u*2+1].v=tr[u].v,tr[u].v=0;
    int mid=(tr[u].l+tr[u].r)/2;
    if(l<=mid) work(l,r,u*2,x);
    if(mid<r) work(l,r,u*2+1,x);
    if(tr[u*2].v==tr[u*2+1].v) tr[u].v=tr[u*2].v;
}
void print(int x)
{
    if(tr[x].v)
    {
        for(int i=tr[x].l; i<=tr[x].r; i++) printf("%c",tr[x].v+'a'-1); return;
    }
    print(x*2),print(x*2+1);
}
int main()
{
    freopen("string.in","r",stdin); freopen("string.out","w",stdout);
    scanf("%d%d\n",&n,&m);
    scanf("%s",st+1);
    build(1,n,1);
    for(int i=1; i<=m; i++)
    {
        int l,r,x;
        scanf("%d%d%d",&l,&r,&x);
        memset(f,0,sizeof(f));
        get_f(l,r,1);
        if(x)
        {
            for(int j=1; j<=26; j++) if(f[j]) work(l,l+f[j]-1,1,j),l+=f[j];
        }else
        {
            for(int j=26; j>=1; j--) if(f[j]) work(l,l+f[j]-1,1,j),l+=f[j];
        }
    }
    print(1);
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值