CF 240F TorCoder(线段树)

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题意:给出一个字符串,有m次操作,每次给出一个区间,把区间重新调整成一个回文序列,如果有多种操作,选择字典序最小的。如果不能操作则不操作。最后输出最终的字符串
刚入手,感觉好神奇的题,其实要自己多思考。想一下,其实还是很简单的。
首先我们统计一下区间内各个字母的数量,然后比较区间长度的奇偶性,就知道是否 可以操作。
面对于回文串的字典序最小,显然是确定,只需要从小到大枚举26个字母就行了。
所以做法是:线段树统计区间内各个字母的数量
然后根据区间长度的奇偶性,判断是否可以操作。
如果可以操作,就进行对称的区间更新。
注意个细节:对于如果是区间长度是奇数的,那么肯定有且只有一种字母的个数是奇数,那么肯定这个字母位于中间,然后其它字母还是按照字母顺序,两边更新。
大概的每次更新的复杂度是大概查询是26*lgn,然后更新是26*lgn,大概跑了2.5s
#include<iostream>
#include<cstdio>
#include<cstring>
#define mem(a,b) memset(a,b,sizeof(a))
#define N 100005
#define lson step<<1
#define rson step<<1|1
using namespace std;
struct Seg_tree{
    int left,right;
    int cnt[26],lazy;
}L[N<<2];
int n,m;
char str[N];
int cnt[26];
void push_up(int step){
    for(int i=0;i<26;i++)
        L[step].cnt[i]=L[lson].cnt[i]+L[rson].cnt[i];
}
void update(int step,int l,int r,int k);
void push_down(int step){
    if(L[step].lazy!=-1){
        int l=L[step].left,r=L[step].right,m=(l+r)>>1;
        update(lson,l,m,L[step].lazy);
        update(rson,m+1,r,L[step].lazy);
        L[step].lazy=-1;
    }
}
void bulid(int step,int l,int r){
    L[step].left=l;
    L[step].right=r;
    L[step].lazy=-1;
    mem(L[step].cnt,0);
    if(l==r){
        L[step].cnt[str[l]-'a']++;
        L[step].lazy=str[l]-'a';
        return ;
    }
    int m=(l+r)>>1;
    bulid(lson,l,m);
    bulid(rson,m+1,r);
    push_up(step);
}
void query(int step,int l,int r){
    if(L[step].left==l&&L[step].right==r){
        for(int i=0;i<26;i++)
            cnt[i]+=L[step].cnt[i];
        return ;
    }
    int m=(L[step].left+L[step].right)>>1;
    push_down(step);
    if(r<=m) query(lson,l,r);
    else if(l>m) query(rson,l,r);
    else {
        query(lson,l,m);
        query(rson,m+1,r);
    }
}
void update(int step,int l,int r,int k){
    if(L[step].left==l&&L[step].right==r){
        mem(L[step].cnt,0);
        L[step].cnt[k]=r-l+1;
        L[step].lazy=k;
        return ;
    }
    push_down(step);
    int m=(L[step].left+L[step].right)>>1;
    if(r<=m) update(lson,l,r,k);
    else if(l>m) update(rson,l,r,k);
    else {
        update(lson,l,m,k);
        update(rson,m+1,r,k);
    }
    push_up(step);
}
void slove(int step){
    if(L[step].left==L[step].right){
        putchar(L[step].lazy+'a');
        return ;
    }
    push_down(step);
    slove(lson);
    slove(rson);
}
int main(){
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    scanf("%d%d%s",&n,&m,str+1);
    bulid(1,1,n);
    while(m--){
        int l,r;
        scanf("%d%d",&l,&r);
        mem(cnt,0);
        query(1,l,r);
        if((r-l+1)&1){
            int k=0,p;
            for(int i=0;i<26;i++)
                if(cnt[i]&1) k++,p=i;
            if(k==1){
                int a=l,b=r;
                cnt[p]--;
                for(int i=0;i<26;i++){
                    if(cnt[i]){
                        update(1,a,a+cnt[i]/2-1,i);
                        update(1,b-cnt[i]/2+1,b,i);
                        a+=cnt[i]/2;
                        b-=cnt[i]/2;
                    }
                }
                update(1,a,b,p);
            }
        }
        else{
            int k=0;
            for(int i=0;i<26;i++)
                if(cnt[i]&1){
                    k=1;
                    break;
                }
            if(!k){
                int a=l,b=r;
                for(int i=0;i<26;i++){
                    if(cnt[i]){
                        update(1,a,a+cnt[i]/2-1,i);
                        update(1,b-cnt[i]/2+1,b,i);
                        a+=cnt[i]/2;
                        b-=cnt[i]/2;
                    }
                }
            }
        }
    }
    slove(1);putchar('\n');
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值