hdu3397 线段树 成段更新

时间:2023-03-08 18:17:06

这题真的呵呵了。敲了很长时间,调了很多bug,把0 1 输出,解决了。最后想取反,怎么搞都有bug,

最后还是看了大牛们的博客。不过这题真的敲得爽,调bug时基本把线段树过程全部弄了一遍。

#include<stdio.h>
#include<string.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 100010
int mark[maxn<<];//成端更新用
int rsum[maxn<<],lsum[maxn<<],msum[maxn<<];//来计算连续的最多的1
int numone[maxn<<];//不连续区间1的个数
int num[maxn<<];//输入数组
int max(int x,int y)
{
return x>y?x:y;
}
int min(int x,int y)
{
return x<y?x:y;
} void pushup(int l,int r,int rt)
{
int len=r-l+;
int m=(l+r)/;
if(mark[rt<<]==mark[rt<<|])
mark[rt]=mark[rt<<];//向上更新维护mark
else mark[rt]=-; if(mark[rt]==)
{
msum[rt]=lsum[rt]=rsum[rt]=numone[rt]=len;//如果mark为1,表明全要为一
}
else if(mark[rt]==)
{
numone[rt]=lsum[rt]=msum[rt]=rsum[rt]=;//类似
}
else//如果mark为-1
{
lsum[rt]=lsum[rt<<];
rsum[rt]=rsum[rt<<|];
msum[rt]=max(msum[rt<<],msum[rt<<|]);
numone[rt]=numone[rt<<]+numone[rt<<|];
if(lsum[rt<<]==m-l+)lsum[rt]=lsum[rt<<]+lsum[rt<<|];
if(rsum[rt<<|]==r-m)rsum[rt]=rsum[rt<<|]+rsum[rt<<];
msum[rt]=max(msum[rt],lsum[rt<<|]+rsum[rt<<]);
}
} void pushdown(int l,int r,int rt)
{ if(mark[rt]!=-)
{
mark[rt<<]=mark[rt<<|]=mark[rt];
if(mark[rt]==)
{
int len=r-l+;
numone[rt<<]=lsum[rt<<]=rsum[rt<<]=msum[rt<<]=len-len/;
numone[rt<<|]=lsum[rt<<|]=rsum[rt<<|]=msum[rt<<|]=len/;
}
else
{
lsum[rt<<]=rsum[rt<<]=msum[rt<<]=numone[rt<<]=;
lsum[rt<<|]=rsum[rt<<|]=msum[rt<<|]=numone[rt<<|]=;
}
mark[rt]=-;
}
} void build(int l,int r,int rt)
{
if(l==r)
{
numone[rt]=lsum[rt]=rsum[rt]=msum[rt]=mark[rt]=num[l];
return;
}
int m=(l+r)/;
build(lson);
build(rson);
pushup(l,r,rt);
}
void updata(int L,int R,int c,int l,int r,int rt)//更新0 和 1的情况
{
if(l>=L&&R>=r)
{
mark[rt]=c;
if(c==)
{
lsum[rt]=rsum[rt]=msum[rt]=;
numone[rt]=;
}
else if(c==)
{
lsum[rt]=rsum[rt]=msum[rt]=r-l+;
numone[rt]=r-l+;
}
return ;
}
pushdown(l,r,rt);
int m=(l+r)/;
if(m>=L)
updata(L,R,c,lson);
if(R>m)
updata(L,R,c,rson);
pushup(l,r,rt);
} void change(int L,int R,int l,int r,int rt)//取反
{
if(l>=L&&R>=r&&mark[rt]!=-)
{
if(mark[rt]==)
lsum[rt]=msum[rt]=rsum[rt]=numone[rt]=;
else if(mark[rt]==)
lsum[rt]=msum[rt]=rsum[rt]=numone[rt]=r-l+;
mark[rt]^=;
return;
}
pushdown(l,r,rt);
int m=(l+r)/;
if(m>=L)
change(L,R,lson);
if(R>m)
change(L,R,rson);
pushup(l,r,rt);
} int query(int L,int R,int l,int r,int rt)//查询1的个数
{
if(l>=L&&R>=r)
{
return numone[rt];
}
pushdown(l,r,rt);
int ret=;
int m=(l+r)/;
if(m>=L)
ret+=query(L,R,lson);
if(R>m)
ret+=query(L,R,rson);
return ret;
} int queryone(int L,int R,int l,int r,int rt)//查询连续的1长
{
if(L<=l&&R>=r)
{
return msum[rt];
}
pushdown(l,r,rt);
int ret=-;
int m=(l+r)/;
if(m>=L)
ret=max(ret,queryone(L,R,lson));
if(R>m)
ret=max(ret,queryone(L,R,rson));
ret=max(ret,min(m-L+,rsum[rt<<])+min(R-m,lsum[rt<<|]));//长度是否合法
return ret;
} int main()
{
int i,n,m,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m); for(i=;i<=n;i++)
scanf("%d",&num[i]); build(,n,);
int x,y,z; while(m--)
{
scanf("%d%d%d",&x,&y,&z);
if(x==)
updata(y+,z+,,,n,);
else if(x==)
updata(y+,z+,,,n,);
else if(x==)
change(y+,z+,,n,);
else if(x==)
printf("%d\n",query(y+,z+,,n,));
else if(x==)
printf("%d\n",queryone(y+,z+,,n,));
}
}
}