CF 240F TorCoder(线段树)

来源:互联网 发布:程序员如何锻炼身体 编辑:程序博客网 时间:2024/06/16 23:00

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

题意:给出一个字符串,有m次操作,每次给出一个区间,把区间重新调整成一个回文序列,如果有多种操作,选择字典序最小的。如果不能操作则不操作。最后输出最终的字符串
http://codeforces.com/problemset/problem/240/F 
刚入手,感觉好神奇的题,其实要自己多思考。想一下,其实还是很简单的。
首先我们统计一下区间内各个字母的数量,然后比较区间长度的奇偶性,就知道是否 可以操作。
面对于回文串的字典序最小,显然是确定,只需要从小到大枚举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|1using 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;}


原创粉丝点击