HDU-4614-Vases and Flowers(线段树)
题目链接:HDU-4614-Vases and Flowers
题意是有n个花瓶在一个线段上,用0~n-1来标记,有两种操作,第一种是从x开始插花,一直向后插y个花,如果一个花瓶里已经插有花,则不能再插,求第一个插花的位置和最后一个插花的位置,如果一朵花都插不了的话,输出"Can not put any one"。第二种操作是将x到y花瓶里的花拿出来,并输出拿出来的花数。
很容易想到用线段树来做,设sum[i]为区间i内花的数量。插花操作首先要找到插花的具体区间,如果[x,n-1]中插满了花,显然是不能插花的,否则我们用二分来找右端点r使得[x,r]内空花瓶的数量为y或者r等于n-1(r==n-1当且仅当区间[x,n-1]内的空花瓶数量小于y) 。 然后通过两个函数find_l和find_r来找左端点和右端点(其实也可以通过二分来找的,定义两层偏序。。),找到左右端点后,更新sum。清空花瓶操作直接更新sum就行了。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=5e4+7; int sum[maxn<<2],n; void push_down(int now,int l,int r) { if(sum[now]==r-l+1) { int mid=(l+r)>>1; sum[now<<1]=mid-l+1; sum[now<<1|1]=r-mid; } else if(sum[now]==0) sum[now<<1]=sum[now<<1|1]=0; } void push_up(int now) { sum[now]=sum[now<<1]+sum[now<<1|1]; } void update(int now,int l,int r,int ul,int ur,int s) { if(ul<=l&&ur>=r) { sum[now]=s*(r-l+1); return ; } if(l==r) return ; push_down(now,l,r); int mid=(l+r)>>1; if(ul<=mid) update(now<<1,l,mid,ul,ur,s); if(ur>mid) update(now<<1|1,mid+1,r,ul,ur,s); push_up(now); } int query(int now,int l,int r,int ql,int qr) { if(ql<=l&&qr>=r) return sum[now]; int mid=(l+r)>>1,res=0; push_down(now,l,r); if(ql<=mid) res+=query(now<<1,l,mid,ql,qr); if(qr>mid) res+=query(now<<1|1,mid+1,r,ql,qr); return res; } int find_l(int now,int l,int r,int ql,int qr) { if(l==r) return l; int mid=(l+r)>>1; if(ql<=mid&&query(1,0,n-1,ql,mid)!=mid-ql+1) return find_l(now<<1,l,mid,ql,qr); else return find_l(now<<1|1,mid+1,r,ql,qr); } int find_r(int now,int l,int r,int ql,int qr) { if(l==r) return l; int mid=(l+r)>>1; if(qr>mid&&query(1,0,n-1,mid+1,qr)!=qr-mid) return find_r(now<<1|1,mid+1,r,ql,qr); else return find_r(now<<1,l,mid,ql,qr); } int main() { int T,m; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); int o,x,y; memset(sum,0,sizeof(sum)); for(int i=0;i<m;i++) { scanf("%d%d%d",&o,&x,&y); if(o==1) { if(query(1,0,n-1,x,n-1)==n-x) { puts("Can not put any one."); continue; } else { int l=x,r=n-1,mid; while(r>l) { mid=(l+r)>>1; if(mid-x+1-query(1,0,n-1,x,mid)>=y) r=mid; else l=mid+1; } int ll=find_l(1,0,n-1,x,r); int rr=find_r(1,0,n-1,x,r); printf("%d %d\n",ll,rr); update(1,0,n-1,ll,rr,1); } } else { printf("%d\n",query(1,0,n-1,x,y)); update(1,0,n-1,x,y,0); } } puts(""); } return 0; }