题意:给定一个区间[0,N-1],初始时每个位置上的数字都是0,有两种操作,1.在位置A开始寻找F(如果没有这么多,则有多少个就找多少个)个数值为0的位置,把位置上的数修改为1,并返回第一个和最后一个修改的位置。2.查询区间[A,B]内1的个数,并把区间[A,B]每个位置上的数修改为0。
对于操作2,直接应用区间更新的懒操作就可以了,而对于操作1,我们可以查询上区间[0,A-1]里有多少有值为0的数,定义其为cnt,然后在整个线段树里查询cnt+1个值为0的数在哪里,同理查询cnt+F个空的瓶子在哪里,这就得到了其对应的起点和终点了。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) const int N=60005; struct node { int lft,rht; int cnt,delay; int mid(){return MID(lft,rht);} void fun(int valu) { delay=valu; if(valu>0) cnt=0; else cnt=rht-lft+1; } void init(){ cnt=rht-lft+1; delay=0; } }; struct Segtree { node tree[N*4]; void PushDown(int ind) { if(tree[ind].delay) { tree[LL(ind)].fun(tree[ind].delay); tree[RR(ind)].fun(tree[ind].delay); tree[ind].delay=0; } } void PushUp(int ind) { tree[ind].cnt=tree[LL(ind)].cnt+tree[RR(ind)].cnt; } void build(int lft,int rht,int ind) { tree[ind].lft=lft; tree[ind].rht=rht; tree[ind].init(); if(lft!=rht) { int mid=tree[ind].mid(); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); } } void updata(int st,int ed,int valu,int ind) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) tree[ind].fun(valu); else { PushDown(ind); int mid=tree[ind].mid(); if(st<=mid) updata(st,ed,valu,LL(ind)); if(ed> mid) updata(st,ed,valu,RR(ind)); PushUp(ind); } } int query(int st,int ed,int ind) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) return tree[ind].cnt; else { PushDown(ind); int mid=tree[ind].mid(); int cnt1=0,cnt2=0; if(st<=mid) cnt1=query(st,ed,LL(ind)); if(ed> mid) cnt2=query(st,ed,RR(ind)); PushUp(ind); return cnt1+cnt2; } } int findPos(int st,int ed,int valu,int ind) { int lft=tree[ind].lft,rht=tree[ind].rht; if(lft==rht) return lft; else { PushDown(ind); int mid=tree[ind].mid(),pos; if(ed<=mid) pos=findPos(st,ed,valu,LL(ind)); else if(st>mid) pos=findPos(st,ed,valu,RR(ind)); else { if(tree[LL(ind)].cnt>=valu) pos=findPos(st,ed,valu,LL(ind)); else pos=findPos(st,ed,valu-tree[LL(ind)].cnt,RR(ind)); } PushUp(ind); return pos; } } }seg; int main() { //freopen("04.in","r",stdin); int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); seg.build(0,n-1,1); for(int i=0;i<m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); if(a==1) { int tmp=seg.query(b,n-1,1); b=min(b,n-1); if(tmp==0) { puts("Can not put any one."); continue; } else if(tmp<=c) c=tmp; int sum=0; if(b-1>=0) sum=seg.query(0,b-1,1); int pos1=seg.findPos(0,n-1,sum+1,1); int pos2=seg.findPos(0,n-1,c+sum,1); seg.updata(pos1,pos2,1,1); printf("%d %d\n",pos1,pos2); } else { b=min(b,n-1); c=min(c,n-1); int sum=seg.query(b,c,1); seg.updata(b,c,-1,1); printf("%d\n",c-b+1-sum); } } puts(""); } return 0; }