#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAX=1e5*2;
int d[MAX],m,n,i,a,b,f,T;
typedef struct P
{
int lnum_0,rnum_0,mnum_0,snum;
int lnum_1,rnum_1,mnum_1;
int left,right,cover;
void set_0(int len)
{
lnum_0=mnum_0=rnum_0=len;
}
void set_1(int len)
{
lnum_1=mnum_1=rnum_1=len;
}
void fun(int f)
{
int len=right-left+1;
if(f==0)
{
set_0(len); set_1(0); snum=0;
cover=f;
}
if(f==1)
{
set_0(0); set_1(len); snum=len;
cover=f;
}
if(f==2)
{
int co=cover;
swap( lnum_0, lnum_1);
swap( rnum_0, rnum_1);
swap( mnum_0, mnum_1);
snum=len-snum;
if(co==-1)
cover=2;
if(co==0)
cover=1;
if(co==1)
cover=0;
if(co==2)
cover=-1;
}
}
}P;
P p[4*MAX];
void pushup(int k)
{
int lt=k<<1,rt=lt+1,llen=p[lt].right-p[lt].left+1,rlen=p[rt].right-p[rt].left+1;
p[k].snum=p[lt].snum+p[rt].snum;
//0有關數據合併
if(p[lt].lnum_0==llen)
p[k].lnum_0=llen+p[rt].lnum_0;
else
p[k].lnum_0=p[lt].lnum_0;
if(p[rt].rnum_0==rlen)
p[k].rnum_0=rlen+p[lt].rnum_0;
else
p[k].rnum_0=p[rt].rnum_0;
p[k].mnum_0=max(max(p[lt].mnum_0,p[rt].mnum_0),p[lt].rnum_0+p[rt].lnum_0);
//1有關數據合併
if(p[lt].lnum_1==llen)
p[k].lnum_1=llen+p[rt].lnum_1;
else
p[k].lnum_1=p[lt].lnum_1;
if(p[rt].rnum_1==rlen)
p[k].rnum_1=rlen+p[lt].rnum_1;
else
p[k].rnum_1=p[rt].rnum_1;
p[k].mnum_1=max(max(p[lt].mnum_1,p[rt].mnum_1),p[lt].rnum_1+p[rt].lnum_1);
}
void pushdown(int k)
{
if(p[k].cover!=-1)
{
int lt=k<<1,rt=lt+1,llen=p[lt].right-p[lt].left+1,rlen=p[rt].right-p[rt].left+1;
int f= p[k].cover;
p[lt].fun(f);
p[rt].fun(f);
p[k].cover=-1;
}
}
void build(int k,int l,int r)
{
p[k].left=l; p[k].right=r; p[k].cover=-1;//cout<<"k= "<<k<<endl;
if(l==r)
{
p[k].lnum_0= p[k].rnum_0= p[k].mnum_0=d[r]?0:1;
p[k].lnum_1= p[k].rnum_1= p[k].mnum_1=d[r]?1:0;
p[k].snum=d[r];
return;
}
int lt=k<<1,rt=lt+1,mid=(l+r)>>1;
build(lt,l,mid);
build(rt,mid+1,r);
pushup(k);
}
void update(int k,int s,int e,int f)
{
if( p[k].left==s&& p[k].right==e)
{
int co= p[k].cover;
if(f<2)
{
p[k].lnum_0= p[k].rnum_0 =p[k].mnum_0=f?0:e-s+1;
p[k].snum=p[k].lnum_1= p[k].rnum_1 =p[k].mnum_1=f?e-s+1:0;
p[k].cover=f;
}
if(f==2)
p[k].fun(2);
return;
}
pushdown(k);
int lt=k<<1,rt=lt+1,mid= (p[k].left+ p[k].right)>>1;
if(e<=mid)
update(lt,s,e,f);
else
if(s>mid)
update(rt,s,e,f);
else
{
update(lt,s,mid,f);
update(rt,mid+1,e,f);
}
pushup(k);
}
int query(int k,int s,int e,int f)
{
pushdown(k);
int mid=( p[k].left +p[k].right)>>1,lt=k<<1,rt=lt+1;
if( p[k].left==s && p[k].right==e)
{
if(f==3)
return p[k].snum;
else
return p[k].mnum_1;
}
if(mid>=e)
return query(lt,s,e,f);
else
if(mid<s)
return query(rt,s,e,f);
else
{
int temp1=query(lt,s,mid,f),temp2=query(rt,mid+1,e,f);
if(f==3)
return temp1+temp2;
else
{
int lm=min(mid-s+1, p[lt].rnum_1),rm=min(e-mid, p[rt].lnum_1);
return max(max(temp1,temp2),lm+rm);
}
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
scanf("%d",d+i);
build(1,0,n-1);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&f,&a,&b);
if(f<=2)
update(1,a,b,f);
else
{
int mm=query(1,a,b,f);
printf("%d\n",mm);
}
}
}
return 0;
}
hdu3397(線段樹區間合併)
是一道坑題。。。大致的思維很好想,只要你知道區間合併,這題的結點維護的變量略多,這題需要用到lazy標記。我用的是一個lazy,寫了200行代碼,好不容易把樣例過了,結果wa。。。瞟了一眼別人的博客,發現大多數是用兩個lazy標記,我那時候想到是我lazy這地方有缺陷,我也不想 用兩個lazy,一來是麻煩,二來是我根本想不到爲什麼用兩個lazy,套用別人的東西,下次 也 不會做。。就醬紫,調試了半天終於ac了。但我還有個問題,就是題目中的數據是100000個,我開110000都會re,果斷開了2*1e6過了。但還是搞不清楚原因,大家指點下。本人寫的代碼太搓了。。以後也要多向大神們學習
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.