重点是求给定区间的最长连续1,这个和poj 3667hotel思路相似
#include <cstdio>
using namespace std;
int in[100010];
struct Node
{
int left, right,sum;
int stat; // 0:区间全为0,1:区间全为1,2:区间有部分为0部分为1
int lmax, rmax, amax; // lmax:包含最左边元素最长1的长度,rmax:包含最右边元素最长1的长度
} tree[300010]; // amax:区间中最长1的长度
int min(int a,int b){
return a>b?b:a;
}
int max(int a,int b){
return a>b?a:b;
}
void updatestatus(int id)
{
if (tree[id].stat == 2)
{
if (tree[id*2].stat == tree[id*2+1].stat && tree[id*2].stat != 2)
tree[id].stat = tree[id*2].stat;
}
}
void updatelength(int id)
{
if (tree[id].stat == 1)
tree[id].sum = tree[id].lmax = tree[id].rmax = tree[id].amax =tree[id].right - tree[id].left + 1;
else if (tree[id].stat == 0)
tree[id].sum = tree[id].lmax = tree[id].rmax = tree[id].amax = 0;
else
{
tree[id].sum = tree[id*2].sum + tree[id*2+1].sum;
tree[id].amax = max(max(tree[id*2].amax, tree[id*2+1].amax), tree[id*2].rmax + tree[id*2+1].lmax);
tree[id].lmax = tree[id*2].lmax;
tree[id].rmax = tree[id*2+1].rmax;
if (tree[id*2].stat == 1)
tree[id].lmax += tree[id*2+1].lmax;
if (tree[id*2+1].stat == 1)
tree[id].rmax += tree[id*2].rmax;
}
}
void Build(int l, int r, int id)
{
tree[id].left = l; tree[id].right = r;
tree[id].lmax = tree[id].rmax = tree[id].amax =0;
if (l == r){
if(in[l]){
tree[id].sum=1;
tree[id].stat=1;
tree[id].lmax = tree[id].rmax = tree[id].amax =1;
}
else{
tree[id].sum=0;
tree[id].stat=0;
tree[id].lmax = tree[id].rmax = tree[id].amax =0;
}
return;
}
int m = (l + r) / 2;
Build(l, m, id * 2);
Build(m + 1, r, id * 2 + 1);
tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
if (tree[id*2].stat == tree[id*2+1].stat && tree[id*2].stat != 2)
tree[id].stat = tree[id*2].stat;
else
tree[id].stat = 2;
updatelength(id); //记着更新状态和长度
}
void update(int l,int r,int flag,int id){
if(tree[id].stat==flag)
return;
if(tree[id].left==l && tree[id].right==r){
tree[id].stat=flag;
updatelength(id);
return;
}
if(tree[id].stat!=2){ // 要下传标记
tree[id*2].stat = tree[id*2+1].stat = tree[id].stat;
tree[id].stat = 2;
updatelength(id*2);
updatelength(id*2+1);
}
int m = (tree[id].left + tree[id].right) / 2;
if (r <= m)
update(l, r, flag, id * 2);
else if (l > m)
update(l , r, flag, id * 2 + 1);
else
update(l, m, flag, id * 2), update(m + 1, r, flag, id * 2 + 1);
updatestatus(id); //记着更新状态和长度
updatelength(id);
}
void updatexor(int l,int r,int id){
if(tree[id].left==l && tree[id].right==r)
if(tree[id].stat==1 || tree[id].stat==0){
tree[id].stat=1^tree[id].stat;
updatelength(id);
return;
}
if(tree[id].stat!=2){ // 要下传标记
tree[id*2].stat = tree[id*2+1].stat = tree[id].stat;
tree[id].stat = 2;
updatelength(id*2);
updatelength(id*2+1);
}
int m = (tree[id].left + tree[id].right) / 2;
if (r <= m)
updatexor(l, r,id * 2);
else if (l > m)
updatexor(l , r, id * 2 + 1);
else
updatexor(l, m, id * 2), updatexor(m + 1, r,id * 2 + 1);
updatestatus(id);
updatelength(id); //记着更新状态和长度
}
int querysum(int l,int r,int id){
if(tree[id].stat==0)return 0;
if(tree[id].stat==1)return r-l+1;
if(tree[id].left==l && tree[id].right==r)
return tree[id].sum;
int m = (tree[id].left + tree[id].right) / 2; //这里不用把标记下传,上面情况已包括
if (r <= m)
return querysum(l, r,id * 2);
else if (l > m)
return querysum(l , r, id * 2 + 1);
else
return querysum(l, m, id * 2)+querysum(m + 1, r,id * 2 + 1);
}
int querycon(int l,int r,int id){
if(tree[id].stat==0)return 0;
if(tree[id].stat==1)return r-l+1;
if(tree[id].left==l && tree[id].right==r)return tree[id].amax;
int m = (tree[id].left + tree[id].right) / 2; //这里不用把标记下传,上面情况已包括
if (r <= m)
return querycon(l, r,id * 2);
else if (l > m)
return querycon(l , r, id * 2 + 1);
else{
int ans1=querycon(l, m, id * 2);
int ans2=querycon(m + 1, r,id * 2 + 1);
int ans3=min(tree[id*2].rmax,m-l+1)+min(tree[id*2+1].lmax,r-m);
return max(max(ans1,ans2),ans3);
}
}
int main()
{
int N, M,T,t,i;
int len,a,b;
scanf("%d",&T);
for(t=1;t<=T;t++){
scanf("%d %d", &N, &M);
for(i=0;i<N;i++)
scanf("%d",&in[i]);
Build(0, N-1, 1);
for (int i = 0; i < M; i++){
int tem;
scanf("%d %d %d", &tem,&a,&b);
if (tem==0)
update(a,b,0,1);
else if(tem==1)
update(a,b,1,1);
else if(tem==2)
updatexor(a,b,1);
else if(tem==3)
printf("%d\n",querysum(a,b,1));
else if(tem==4)
printf("%d\n",querycon(a,b,1));
}
}
return 0;
}