题目
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]).
区间染色
pushup中tag也要上推???感觉是吧。不知道不知道。 一会儿写染色后来补 。
这个和区间染色是肯定不同的啊。因为其中 异或 的时候相当于对 tag[pos]!=-1的左右区间 分别染色。故此时需要判断tag[pos]!=-1? 。。若等于-1的话。区间还要继续往下划分。tag 一定要上推。而且求 sum fs …等等与 tag的值有关。
#include <algorithm>
#include <cstdio>
using namespace std;
const int N=100005*4;
int sum[N],tag[N],fs[N],ls[N],rs[N],cur[N];
void pushup(int ln,int rn,int pos)
{
if(tag[pos<<1]==tag[pos<<1|1])
tag[pos]=tag[pos<<1];
else
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;
}
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 chanpoint(int cl,int cr,int l,int r,int pos)
{
if(cl<=l&&r<=cr&&tag[pos]!=-1)
{
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)
chanpoint(cl,cr,l,mid,pos<<1);
if(cr>mid)
chanpoint(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)
chanpoint(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));
}
}
}