题目大意
给定一个区间[0,N-1],初始时每个位置上的数字都是0,可以对其进行以下两种操作:
1、在位置A开始寻找F(如果没有这么多,则有多少个就找多少个)个数值为0的位置,把位置上的数修改为1,并返回第一个和最后一个修改的位置
2、查询区间[a,b]内1的个数,并把区间[a,b]每个位置上的数修改为0
题解
基础的线段树~~~第一个操作可以用二分求出始末位置,然后进行区间修改,第二问就是区间查询和区间修改
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 50005 #define lson l,m,s<<1 #define rson m+1,r, s<<1|1 int msum[MAXN<<2],setv[MAXN<<2],sumv[MAXN<<2]; void PushUp(int s,int m) { msum[s]=msum[s<<1]+msum[s<<1|1]; sumv[s]=sumv[s<<1]+sumv[s<<1|1]; } void PushDown(int s,int m) { if(setv[s]!=-1) { setv[s<<1]=setv[s<<1|1]=setv[s]; msum[s<<1]=setv[s]?(m-(m>>1)):0; msum[s<<1|1]=setv[s]?(m>>1):0; sumv[s<<1]=setv[s]?0:(m-(m>>1)); sumv[s<<1|1]=setv[s]?0:(m>>1); setv[s]=-1; } } void build(int l,int r,int s) { msum[s]=r-l+1,setv[s]=-1,sumv[s]=0; if(l==r) return; int m=(l+r)>>1; build(lson); build(rson); } int query(int ql,int qr,int l,int r,int s,int p) { if(ql<=l&&r<=qr) { if(p==1) return sumv[s]; else return msum[s]; } PushDown(s,r-l+1); int m=(l+r)>>1,ans=0; if(ql<=m) ans+=query(ql,qr,lson,p); if(qr>m) ans+=query(ql,qr,rson,p); return ans; } void update(int ql,int qr,int l,int r,int s,int d) { if(ql<=l&&r<=qr) { msum[s]=d?r-l+1:0; sumv[s]=d?0:r-l+1; setv[s]=d; return; } PushDown(s,r-l+1); int m=(l+r)>>1; if(ql<=m) update(ql,qr,lson,d); if(qr>m) update(ql,qr,rson,d); PushUp(s,r-l+1); } int main(void) { int T,m,n,a,b,k,ll,rr; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); build(0,n-1,1); while(m--) { int t; scanf("%d%d%d",&k,&a,&b); if(k==1) { t=query(a,n-1,0,n-1,1,2); if(t==0) printf("Can not put any one. "); else { if(t<b) b=t; int l,r,mid,ans; if(a-1>=0) ans=query(0,a-1,0,n-1,1,2); else ans=0; l=a; r=n-1; while(l<=r) { mid=(l+r)>>1; if(query(0,mid,0,n-1,1,2)-ans>=1) r=mid-1; else l=mid+1; } ll=l; l=a; r=n-1; while(l<=r) { mid=(l+r)>>1; if(query(0,mid,0,n-1,1,2)-ans>=b) r=mid-1; else l=mid+1; } rr=l; printf("%d %d ",ll,rr); update(ll,rr,0,n-1,1,0); } } else { printf("%d ",query(a,b,0,n-1,1,1)); update(a,b,0,n-1,1,1); } } printf(" "); } }