https://codeforces.com/contest/145/problem/E
元素值只有4,7转换成01序列,操作一区间反转,操作二询问类LIS
我们先考虑操作二
应该维护什么量呢
线段树维护量,是通过左子树和右子树的信息合并来维护的
大致有两种情况
可以发现可以通过Leftcnt0+Right类LIS
Left类LIS+Rightcnt1
然后我们把一边是全是0,一边全是1的情况也考虑进去了
这样我们把这二种情况取max即可
接下来我们考虑加上第一个操作
(00001111)->(11110000)
维护的量需要有所变化
显然,1的数量和0的数量要交换
类LIS->类LDS
于是我们又需要维护类LDS
同理
有大致两种
Left类LDS+RIghtcnt0
Leftcnt1+Right类LDS
同理取max
于是取反的时候,LDS和LIS要交换
到此维护量的操作就解释完了
code
// Problem: E. Lucky Queries
// Contest: Codeforces - Codeforces Round 104 (Div. 1)
// URL: https://codeforces.com/contest/145/problem/E
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
using namespace std;
const int N=1e6+9;
string s;
//线段树
struct SEG{
#define INF (1<<31)
#define ll long long
#define tl(id) (id<<1)
#define tr(id) (id<<1|1)
#define li inline
struct node{
int tag;
int cnt0,cnt1;
int lis,lds;
}seg[N<<2];
li int inrange(int L,int R,int l,int r){return l<=L && R<=r;}
li int outofrange(int L,int R,int l,int r){return L>r || R<l;}
li void pushup(int id){
seg[id].cnt0=seg[tl(id)].cnt0+seg[tr(id)].cnt0;
seg[id].cnt1=seg[tl(id)].cnt1+seg[tr(id)].cnt1;
seg[id].lis=max(seg[tl(id)].cnt0+seg[tr(id)].lis,seg[tl(id)].lis+seg[tr(id)].cnt1);
seg[id].lds=max(seg[tl(id)].cnt1+seg[tr(id)].lds,seg[tl(id)].lds+seg[tr(id)].cnt0);
}
li void build(const int id,int l,int r){
seg[id].tag=0;
if(l==r){
seg[id].cnt0=(s[l]-'0'==4);
seg[id].cnt1=(s[l]-'0'==7);
seg[id].lis=seg[id].lds=1;
return;
}
int mid=(l+r)>>1;
build(tl(id),l,mid);
build(tr(id),mid+1,r);
pushup(id);
}
li void maketag(int id,int l,int r){
seg[id].tag^=1;
swap(seg[id].cnt0,seg[id].cnt1);
swap(seg[id].lis,seg[id].lds);
}
li void pushdown(int id,int l,int r){
if(!seg[id].tag){
return;
}
int mid=(l+r)>>1;
maketag(tl(id),l,mid);
maketag(tr(id),mid+1,r);
seg[id].tag=0;
}
li void modify(int id,int L,int R,int l,int r){
if(inrange(L,R,l,r)){
maketag(id,L,R);
}else if(!outofrange(L,R,l,r)){
int mid=(L+R)>>1;
pushdown(id,L,R);
modify(tl(id),L,mid,l,r);
modify(tr(id),mid+1,R,l,r);
pushup(id);
}
}
}t;
#define node SEG::node
int main(){
int n,m;
cin>>n>>m;
cin>>s;//4->0,7->1
s=' '+s;
t.build(1,1,n);
for(int i=1;i<=m;i++){
string op;
cin>>op;
if(op[0]=='s'){
int l,r;
cin>>l>>r;
t.modify(1,1,n,l,r);//xor;
}else{
cout<<t.seg[1].lis<<'\n';
}
}
return 0;
}