分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小
#include<iostream> #include<cmath> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=5e4+5; int n,m,T,c[N<<2],lz[N<<2]; void build(int rt,int l,int r){ lz[rt]=-1; if(l==r){c[rt]=1;return;} int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r); c[rt]=c[rt<<1]+c[rt<<1|1]; } void pushdown(int rt,int l,int r){ if(lz[rt]!=-1){ int m=(l+r)>>1; c[rt<<1]=lz[rt]*(m-l+1); c[rt<<1|1]=lz[rt]*(r-m); lz[rt<<1]=lz[rt<<1|1]=lz[rt]; lz[rt]=-1; } } int t; void modify(int rt,int l,int r,int x,int y){ if(x<=l&&r<=y){ c[rt]=t*(r-l+1); lz[rt]=t; return; } int m=(l+r)>>1; pushdown(rt,l,r); if(x<=m)modify(rt<<1,l,m,x,y); if(y>m)modify(rt<<1|1,m+1,r,x,y); c[rt]=c[rt<<1]+c[rt<<1|1]; } int ask(int rt,int l,int r,int x,int y){ if(x<=l&&r<=y)return c[rt]; int m=(l+r)>>1,ans=0; pushdown(rt,l,r); if(x<=m)ans+=ask(rt<<1,l,m,x,y); if(y>m)ans+=ask(rt<<1|1,m+1,r,x,y); return ans; } int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); build(1,1,n); while(m--){ int op,x,y; scanf("%d%d%d",&op,&x,&y); if(op==2){ ++x,++y; printf("%d ",y-x+1-ask(1,1,n,x,y)); t=1;modify(1,1,n,x,y); continue; } ++x; y=min(y,ask(1,1,n,x,n)); if(!y){ printf("Can not put any one. "); continue; } int ans1,ans2; int l=x,r=n; while(l<r){ int mid=(l+r)>>1,cur=ask(1,1,n,x,mid); if(!cur)l=mid+1; else r=mid; } ans1=(l+r)>>1; l=x,r=n; while(l<r){ int mid=(l+r)>>1,cur=ask(1,1,n,x,mid); if(cur<y)l=mid+1; else r=mid; } ans2=(l+r)>>1; t=0;modify(1,1,n,ans1,ans2); printf("%d %d ",--ans1,--ans2); } printf(" "); } return 0; }