这个题的话思路不复杂
对于每个1操作,利用两次二分来查找它的操作区间,然后把这个区间都赋值为1,
对于每个2操作,直接把区间赋值为零好了。。
线段树维护一个sum存储当前区间为值0的点有多少个就好
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
struct rec{int lch,rch,sum,biao,l,r;}tree[200100];
int n,m,tot,ans_r,ans_l;
void updata(int x)
{
if (tree[x].biao==0) return ;
if (tree[x].biao==1)
{
if (tree[x].lch!=0)
{
int lc=tree[x].lch;
tree[lc].sum=tree[lc].r-tree[lc].l+1;
tree[lc].biao=tree[x].biao;
}
if (tree[x].rch!=0)
{
int rc=tree[x].rch;
tree[rc].sum=tree[rc].r-tree[rc].l+1;
tree[rc].biao=tree[x].biao;
}
tree[x].biao=0;
}
if (tree[x].biao==2)
{
if (tree[x].lch!=0)
{
int lc=tree[x].lch;
tree[lc].sum=0;
tree[lc].biao=tree[x].biao;
}
if (tree[x].rch!=0)
{
int rc=tree[x].rch;
tree[rc].sum=0;
tree[rc].biao=tree[x].biao;
}
tree[x].biao=0;
}
}
void maketree(int l,int r)
{
int now=++tot;
tree[now].l=l;
tree[now].r=r;
if (l==r)
{
tree[now].sum=1;
return ;
}
int mid=(l+r)>>1;
tree[now].lch=tot+1;maketree(l,mid);
tree[now].rch=tot+1;maketree(mid+1,r);
tree[now].sum=tree[tree[now].lch].sum+tree[tree[now].rch].sum;
}
void change(int x,int l,int r,int w)
{
updata(x);
if (tree[x].l>=l&&tree[x].r<=r)
{
if (w==0) tree[x].sum=tree[x].r-tree[x].l+1;
if (w==1) tree[x].sum=0;
tree[x].biao=w+1;
return ;
}
int mid=(tree[x].l+tree[x].r)>>1;
if (l<=mid) change(tree[x].lch,l,r,w);
if (r>mid) change(tree[x].rch,l,r,w);
tree[x].sum=tree[tree[x].lch].sum+tree[tree[x].rch].sum;
}
int getsum(int x,int l,int r)
{
int now=0;
updata(x);
if (tree[x].l>=l&&tree[x].r<=r)
return tree[x].sum;
int mid=(tree[x].l+tree[x].r)>>1;
if (l<=mid) now+=getsum(tree[x].lch,l,r);
if (r>mid) now+=getsum(tree[x].rch,l,r);
return now;
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int a,b,c,ll,rr,t,tmp,mid;
scanf("%d",&t);
while (t--)
{
tot=0;
memset(tree,0,sizeof(tree));
scanf("%d%d",&n,&m);
maketree(1,n);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if (a==1)
{
b++;
tmp=getsum(1,b,n);
if (tmp==0)
{
printf("Can not put any one.\n");
continue;
}
tmp=min(tmp,c);
ll=b,rr=n;
while (ll!=rr)
{
mid=(ll+rr)>>1;
if (getsum(1,b,mid)>=tmp) rr=mid;
else ll=mid+1;
}
ans_r=rr;ans_l=ll;ll=b;rr=rr;
while (ll!=rr)
{
mid=((ll+rr)>>1)+1;
if (getsum(1,mid,ans_r)>=tmp) ll=mid;
else rr=mid-1;
}
printf("%d %d\n",ll-1,ans_r-1);
change(1,ll,ans_r,1);
}
if (a==2)
{
b++;c++;
tmp=getsum(1,b,c);
change(1,b,c,0);
printf("%d\n",c-b+1-tmp);
}
}
printf("\n");
}
return 0;
}
刚会学校的时候写这个东西还是有点费劲的,但是现在感觉已经是随手写了。果然是在进步吗,真是太好了。