题意:
长度为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);
}
}
}