hdu3667:
题意:定义两种操作,询问最大连续的空间,返回首地址;清除以及将一段区间置1。
思路:线段树,定义三个数组分别表示从左,右,中,的最大连续长度,注意向上更新时合并区间的操作。
写了一段时间,错了很多地方。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 55555
using namespace std;
int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2];
int col[maxn<<2];
void PushUp(int rt,int m)
{
lsum[rt]=lsum[rt<<1];
rsum[rt]=rsum[rt<<1|1];
if(lsum[rt]==m-(m>>1)) lsum[rt]+=lsum[rt<<1|1];
if(rsum[rt]==(m>>1)) rsum[rt]+=rsum[rt<<1];//写错了
msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);//写错了
}
void PushDown(int rt,int m)
{
if(col[rt]!=-1)
{
col[rt<<1]=col[rt<<1|1]=col[rt];
lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=col[rt]?0:m-(m>>1);
lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=col[rt]?0:(m>>1);
col[rt]=-1;
}
}
void build(int l,int r,int rt)
{
lsum[rt]=msum[rt]=rsum[rt]=r-l+1;
col[rt]=-1;
if(l==r)
{
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
}
int query(int c,int l,int r,int rt)
{
if(l==r)
{
return l;//直到一个点为止
}
PushDown(rt,r-l+1);
int m=(l+r)>>1;
if(msum[rt<<1]>=c) return query(c,lson);
else if(rsum[rt<<1]+lsum[rt<<1|1]>=c) return m-rsum[rt<<1]+1;
else return query(c,rson);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
lsum[rt]=rsum[rt]=msum[rt]=c?0:r-l+1;
col[rt]=c;
return ;//第二个错
}
PushDown(rt,r-l+1);
int m=(l+r)>>1;
if(L<=m)
update(L,R,c,lson);
if(R>m)
update(L,R,c,rson);
PushUp(rt,r-l+1);
}
int main()
{
int n,m,ord,cc,p,a,b;
scanf("%d%d",&n,&m);
build(1,n,1);
for(int i=0;i<m;i++)
{
scanf("%d",&ord);
if(ord==1)
{
scanf("%d",&cc);
if(msum[1]<cc)
printf("0\n");
else
{
p=query(cc,1,n,1);
printf("%d\n",p); //第一个错
update(p,p+cc-1,1,1,n,1);//1表示覆盖
}
}
else
{
scanf("%d%d",&a,&b);
update(a,a+b-1,0,1,n,1);//0表示清除
//错误三 区间写错了
}
}
return 0;
}