傳送門:CDOJ1592
題目大意:
給你一個長度爲n的序列,只有1和0,m次操作,兩種操作,第一種爲將一段區間異或上0,
一種爲詢問一段區間最長連續1的長度
題目思路:
這是線段樹區間合併的模板題,在普通線段樹上改進下維護每個區間向左向右連續1和0的長度
和區間最長連續的長度,這樣向上更新的時候爲 ,左右連續等於子區間連續,如果左右連續填
滿了子區間,則還要加上相反連續的和,例如子區間的向左連續爲區間長度,則父區間的向左
連續爲子區間左連續加上子右區間的左連續,然後最大連續爲左右子區間和中間連續的最大值
向下更新爲記錄個懶惰標記,每次將子區間的連續0和1交換,因爲是異或,0變1,1變0,
更新的時候寫法差不多,查詢的時候則要返回兩邊最大和中間連續的最大值
AC代碼:
/**
CDOJ1592 線段樹區間合併模板題 HDU3911
*/
#include<bits/stdc++.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define Max(a,b) (a)>(b)?(a):(b)
#define Min(a,b) (a)<(b)?(a):(b)
const int maxn = 1e5+100;
struct ST
{
int lone,rone,lzero,rzero,sumone,sumzero;
int cover;
int l,r;
}Tree[maxn<<2];
int n;
//向上更新
void push_up(int rt)
{
Tree[rt].lone = Tree[rt<<1].lone;
Tree[rt].lzero = Tree[rt<<1].lzero;
//子區間填滿
if(Tree[rt<<1].lone==Tree[rt<<1].r-Tree[rt<<1].l+1)Tree[rt].lone+=Tree[rt<<1|1].lone;
if(Tree[rt<<1].lzero==Tree[rt<<1].r-Tree[rt<<1].l+1)Tree[rt].lzero+=Tree[rt<<1|1].lzero;
Tree[rt].rone = Tree[rt<<1|1].rone;
Tree[rt].rzero = Tree[rt<<1|1].rzero;
if(Tree[rt<<1|1].rone==Tree[rt<<1|1].r-Tree[rt<<1|1].l+1)Tree[rt].rone+=Tree[rt<<1].rone;
if(Tree[rt<<1|1].rzero==Tree[rt<<1|1].r-Tree[rt<<1|1].l+1)Tree[rt].rzero+=Tree[rt<<1].rzero;
Tree[rt].sumone = max(Tree[rt<<1].rone+Tree[rt<<1|1].lone,max(Tree[rt<<1].sumone,Tree[rt<<1|1].sumone));
Tree[rt].sumzero = max(Tree[rt<<1].rzero+Tree[rt<<1|1].lzero,max(Tree[rt<<1].sumzero,Tree[rt<<1|1].sumzero));
}
void Build(int l,int r,int rt)
{
Tree[rt].l = l,Tree[rt].r = r,Tree[rt].cover = 0;
if(l==r)
{
int x;scanf("%d",&x);
Tree[rt].lone = Tree[rt].rone = Tree[rt].sumone = x;
Tree[rt].lzero = Tree[rt].rzero = Tree[rt].sumzero = !x;
return ;
}
int mid = (l+r)>>1;
Build(lson);
Build(rson);
push_up(rt);
}
void pushdown(int rt)
{
if(Tree[rt].cover)
{
Tree[rt<<1].cover^=1;
Tree[rt<<1|1].cover^=1;
Tree[rt].cover = 0;
//0,1交換
swap(Tree[rt<<1].lone,Tree[rt<<1].lzero);
swap(Tree[rt<<1].sumone,Tree[rt<<1].sumzero);
swap(Tree[rt<<1].rone,Tree[rt<<1].rzero);
swap(Tree[rt<<1|1].lone,Tree[rt<<1|1].lzero);
swap(Tree[rt<<1|1].sumone,Tree[rt<<1|1].sumzero);
swap(Tree[rt<<1|1].rone,Tree[rt<<1|1].rzero);
}
}
void updata(int l,int r,int rt)
{
if(l<=Tree[rt].l&&Tree[rt].r<=r)
{
Tree[rt].cover^=1;
swap(Tree[rt].lone,Tree[rt].lzero);
swap(Tree[rt].sumone,Tree[rt].sumzero);
swap(Tree[rt].rone,Tree[rt].rzero);
return ;
}
pushdown(rt);
int mid = (Tree[rt].r+Tree[rt].l)>>1;
if(r<=mid)
{
updata(l,r,rt<<1);
}
else if(l>mid)
{
updata(l,r,rt<<1|1);
}
else
{
updata(l,mid,rt<<1);
updata(mid+1,r,rt<<1|1);
}
push_up(rt);
}
int quary(int l,int r,int rt)
{
if(l<=Tree[rt].l&&Tree[rt].r<=r)
{
return Tree[rt].sumone;
}
pushdown(rt);
int mid = (Tree[rt].r+Tree[rt].l)>>1;
if(l>mid)return quary(l,r,rt<<1|1);
else if(r<=mid)return quary(l,r,rt<<1);
else
{
int ans1 = quary(l,mid,rt<<1);
int ans2 = quary(mid+1,r,rt<<1|1);
return max(min(mid-l+1,Tree[rt<<1].rone)+min(r-mid,Tree[rt<<1|1].lone),max(ans1,ans2));
}
}
int main()
{
int m;
while(cin>>n)
{
Build(1,n,1);
cin>>m;
while(m--)
{
int id,x,y;
scanf("%d%d%d",&id,&x,&y);
if(id)
{
updata(x,y,1);
}
else
{
printf("%d\n",quary(x,y,1));
}
}
}
return 0;
}