Codeforces Round #104 (Div. 1) E. Lucky Queries (线段树)

题意:

        长度为n的47串,两种操作,一种是区间变换,即4变7,7变4,一种是询问,问最长的非严格递增子序列长度

思路:

        线段树维护即可,47可以抽象成01串,变换就是异或,存储全0串最长长度,全1串最长长度,000..111串长度,111…000串长度,变换就让全0和全1交换,000…111和111…000交换,然后pushup的时候全1和全0可以根据左右儿子直接相加得到,000….111和111…000可以由儿子推出

错误及反思:

代码:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N = 1001000;
int segtree[N<<2][4],lazy[N<<2];//  0 for 0-0  1 for 0-1  2 for 1-0 3 for 1-1
char s[N];
int n,m;

void pushup(int rt){
    segtree[rt][0]=segtree[rt<<1][0]+segtree[rt<<1|1][0];
    segtree[rt][3]=segtree[rt<<1][3]+segtree[rt<<1|1][3];
    segtree[rt][1]=max(segtree[rt<<1][1]+segtree[rt<<1|1][3],segtree[rt<<1][0]+max(segtree[rt<<1|1][1],segtree[rt<<1|1][3]));
    segtree[rt][2]=max(segtree[rt<<1][2]+segtree[rt<<1|1][0],segtree[rt<<1][3]+max(segtree[rt<<1|1][2],segtree[rt<<1|1][0]));

}

void build(int l,int r,int rt){
    if(l==r){
        if(s[l]==1) segtree[rt][3]=1;
        else segtree[rt][0]=1;
        segtree[rt][2]=1;
        segtree[rt][1]=1;
        return ;
    }
    int m=(l+r)/2;
    build(lson);
    build(rson);
    pushup(rt);
}

void Swap(int rt){
    swap(segtree[rt][0],segtree[rt][3]);
    swap(segtree[rt][1],segtree[rt][2]);
}
void pushdown(int rt){
    if(lazy[rt]){
        Swap(rt<<1); Swap(rt<<1|1);
        lazy[rt<<1]++; lazy[rt<<1|1]++;
        lazy[rt<<1]%=2;lazy[rt<<1|1]%=2;
        lazy[rt]=0;
    }
}

void update(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r){
        Swap(rt);
        lazy[rt]++;
        lazy[rt]%=2;
        return ;
    }
    pushdown(rt);
    int m=(l+r)/2;
    if(L<=m) update(L,R,lson);
    if(R>m) update(L,R,rson);
    pushup(rt);
}

int main(){
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)
        if(s[i]=='4') s[i]=0;
        else s[i]=1;
    build(1,n,1);
    while(m--){
        char t[10]; scanf("%s",t);
        if(t[0]=='c') printf("%d\n",max(max(segtree[1][1],segtree[1][0]),segtree[1][3]));
        else{
            int l,r; scanf("%d%d",&l,&r);
            update(l,r,1,n,1);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值