题目
lxhgww得到一个包含n个字符的序列,这些字符都是“0”或“1”。
我们有五个操作:
改变操作:
将[a, b]中的所有字符改为’0’
将[a, b]中的所有字符改为’1’
把所有的0都变成1把所有的1都变成0
输出操作:
输出[a, b]中’1’的个数
输出[a, b]中最长的连续“1”字符串的长度。
输入
第一行中的T(T<=10)是箱号。
每一种情况在第一行有两个整数:n和m (1 <= n, m <= 100000)。
下一行包含n个字符,“0”或“1”由空格分隔。
m行为操作:
op a b: 0 <= op <= 4, 0 <= a <= b < n。
输出
对于每个输出操作,输出结果。
用 ls[ ] ,rs[ ] 前后缀连续为1的数列长度。
fs[pos]=max( fs[pos<<1],fs[pos<<1|1]).
fs[pos]=max( fs[pos], min(mid-cl+1,rs[pos<<1])+min(cr-mid,ls[pos<<1|1]).
区间染色
其中 异或 的时候相当于对 tag[pos]!=-1的左右区间 分别染色。故此时需要判断tag[pos]!=-1? 。。若等于-1的话。区间还要继续往下划分。因此tag 一定要上推。为什么要有pushdown呢。因为很好理解吧。
#include<bits/stdc++.h>
using namespace std;
const int N=100005<<2;
int sum[N],tag[N],fs[N],ls[N],rs[N],cur[N];
void pushup(int ln,int rn,int pos){
(tag[pos<<1]==tag[pos<<1|1])?tag[pos]=tag[pos<<1]:tag[pos]=-1;
if(tag[pos]!=-1) sum[pos]=fs[pos]=ls[pos]=rs[pos]=(tag[pos]?(ln+rn):0);
else{
sum[pos]=sum[pos<<1]+sum[pos<<1|1];
fs[pos]=max(fs[pos<<1],fs[pos<<1|1]);
fs[pos]=max(fs[pos],rs[pos<<1]+ls[pos<<1|1]);
ls[pos]=ls[pos<<1],rs[pos]=rs[pos<<1|1];
if(ls[pos<<1]==ln) ls[pos]=ln+ls[pos<<1|1];
if(rs[pos<<1|1]==rn) rs[pos]=rs[pos<<1]+rn;
}
}
void build(int l,int r,int pos){
if(l==r){
tag[pos]=cur[l],sum[pos]=fs[pos]=ls[pos]=rs[pos]=cur[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,pos<<1),build(mid+1,r,pos<<1|1);
pushup(mid-l+1,r-mid,pos);
}
void pushdown(int ln,int rn,int pos){
if(tag[pos]==-1) return;
tag[pos<<1]=tag[pos<<1|1]=tag[pos];
sum[pos<<1]=fs[pos<<1]=ls[pos<<1]=rs[pos<<1]=(tag[pos]?ln:0);
sum[pos<<1|1]=fs[pos<<1|1]=ls[pos<<1|1]=rs[pos<<1|1]=(tag[pos]?rn:0);
//tag[pos]=-1; //将此处的标记取消。要不要都可以 因为有tag上推
}
void chanspan(int cl,int cr,int val,int l,int r,int pos){
if(cl<=l&&r<=cr){
tag[pos]=val,sum[pos]=fs[pos]=ls[pos]=rs[pos]=(tag[pos]?(r-l+1):0);
return;
}
int mid=(l+r)>>1;
pushdown(mid-l+1,r-mid,pos);
if(cl<=mid) chanspan(cl,cr,val,l,mid,pos<<1);
if(cr>mid) chanspan(cl,cr,val,mid+1,r,pos<<1|1);
pushup(mid-l+1,r-mid,pos);
}
void chanxor(int cl,int cr,int l,int r,int pos){ //区间异或
if(cl<=l&&r<=cr&&tag[pos]!=-1){//这种做法必须找到左右区间染色相同的才可.故tag上推很必要
tag[pos]^=1,sum[pos]=fs[pos]=ls[pos]=rs[pos]=(tag[pos]?(r-l+1):0);
return;
}
int mid=(l+r)>>1;
pushdown(mid-l+1,r-mid,pos);
if(cl<=mid) chanxor(cl,cr,l,mid,pos<<1);
if(cr>mid) chanxor(cl,cr,mid+1,r,pos<<1|1);
pushup(mid-l+1,r-mid,pos);
}
int series_1(int cl,int cr,int l,int r,int pos){
if(cl<=l&&r<=cr) return fs[pos];
int mid=(l+r)>>1;
pushdown(mid-l+1,r-mid,pos);
int ans=-1;
if(cl<=mid) ans=max(ans,series_1(cl,cr,l,mid,pos<<1));
if(cr>mid) ans=max(ans,series_1(cl,cr,mid+1,r,pos<<1|1));
ans=max(ans,min(mid-cl+1,rs[pos<<1])+min(cr-mid,ls[pos<<1|1]));//注意!!!需要比较一下.自己想想就知道为什么了
return ans;
}
int num_1(int cl,int cr,int l,int r,int pos){
if(cl<=l&&r<=cr) return sum[pos];
int mid=(l+r)>>1;
pushdown(mid-l+1,r-mid,pos);
int ans=0;
if(cl<=mid) ans+=num_1(cl,cr,l,mid,pos<<1);
if(cr>mid) ans+=num_1(cl,cr,mid+1,r,pos<<1|1);
return ans;
}
int main(){
int T;scanf("%d",&T);
while(T--){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&cur[i]);
build(1,n,1);
while(m--){
int k,cl,cr;scanf("%d%d%d",&k,&cl,&cr),++cl,++cr;
if(k==0) chanspan(cl,cr,0,1,n,1);
if(k==1) chanspan(cl,cr,1,1,n,1);
if(k==2) chanxor(cl,cr,1,n,1);
if(k==3) printf("%d\n",num_1(cl,cr,1,n,1));
if(k==4) printf("%d\n",series_1(cl,cr,1,n,1));
}
}
}