codeforces 145E - Lucky Queries

来源:互联网 发布:python cuda windows 编辑:程序博客网 时间:2024/05/21 10:46

    题目大意:给一个长度为n的47序列(就是只有4和7),两种操作:

操作1:count 要求输出当前数列的最长非下降子序列(注意是子序列,不是子串。。。一开始没看清题WA半天)。

操作2 : switch l r 将区间[l,r]之间的数反转(这里的反转指的是4变成7 7变成4)

然后就是给你一堆操作,对每一个操作1输出相应的值。。。

PS:这竟然是div1 的 E,我觉得就是一道很中规中矩的线段树啊。。。

    思路:在线段树中维护一下值:

len4表示全是4的最长子序列。

len7表示全是7的最长子序列。

len47表示以4开头以7结尾的最长子序列。

rev当然是懒惰标记啦。。。

对于操作2,因为反转之后对len4,len7,len47的值影响较大(主要还是len47),所以我一般对这样的题都是直接维护两个值,一个是当前的,一个是反转后的,当进行反转操作时再交换就好了。

对于两个区间合并 len4和len7很好更新,这里就不讲了,主要还是len47(其实也很简单的。。。),len47就三种情况,1,左边的len4+右边的len47。2,左边的len4+右边的len7。3左边的len47+右边的len7。三种情况取个大的就行了。还有。。。没什么要注意了吧。。两个操作都是很普通的线段树操作,没什么可讲的了,代码实现如下。

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#define maxn 1000100#define mid ((t[p].l+t[p].r)>>1)#define ls (p<<1)#define rs (ls|1)using namespace std;struct tree{    int l,r;    int len4[2],len7[2],len47[2];    int rev;}t[maxn<<2];int a[maxn];int max(int a,int b){    return a>b?a:b;}void pushup(int p,int c){    t[p].len4[c]=t[ls].len4[c]+t[rs].len4[c];    t[p].len7[c]=t[ls].len7[c]+t[rs].len7[c];    int tmp=t[ls].len4[c]+max(t[rs].len7[c],t[rs].len47[c]);    t[p].len47[c]=max(tmp,t[ls].len47[c]+t[rs].len7[c]);}void change(int p){    t[p].rev^=1;    swap(t[p].len4[0],t[p].len4[1]);    swap(t[p].len7[0],t[p].len7[1]);    swap(t[p].len47[0],t[p].len47[1]);}void pushdown(int p){    if(t[p].rev)    {        change(ls);        change(rs);        t[p].rev=0;    }}void build(int p,int l,int r){    t[p].l=l,t[p].r=r,t[p].rev=0;    if(l==r)    {        if(a[l])        {            t[p].len7[0]=t[p].len4[1]=1;            t[p].len7[1]=t[p].len4[0]=0;        }        else        {            t[p].len7[0]=t[p].len4[1]=0;            t[p].len7[1]=t[p].len4[0]=1;        }        t[p].len47[0]=t[p].len47[1]=0;        return;    }    build(ls,l,mid);    build(rs,mid+1,r);    pushup(p,0);    pushup(p,1);}int get(int p,int x){    if(t[p].l==t[p].r)    {        if(t[p].len4[0])        return 0;        return 1;    }    pushdown(p);    if(x>mid)    return get(rs,x);    return get(ls,x);}void reverse(int p,int l,int r){    if(t[p].l==l&&t[p].r==r)    {        change(p);        return;    }    pushdown(p);    if(l>mid)    reverse(rs,l,r);    else if(r<=mid)    reverse(ls,l,r);    else    {        reverse(ls,l,mid);        reverse(rs,mid+1,r);    }    pushup(p,0);    pushup(p,1);}char str[maxn],tmp[10];int main(){    int n,m,i;    scanf("%d%d",&n,&m);    scanf("%s",str+1);    for(i=1;i<=n;i++)    {        if(str[i]=='4')        a[i]=0;        else        a[i]=1;    }    build(1,1,n);    while(m--)    {        int l,r;        scanf("%s",tmp);        if(tmp[0]=='s')        {            scanf("%d%d",&l,&r);            reverse(1,l,r);        }        else        {            printf("%d\n",max(t[1].len4[0],max(t[1].len7[0],t[1].len47[0])));        }    }    return 0;}