hdu 4614 线段树 二分
Posted wjhstudy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4614 线段树 二分相关的知识,希望对你有一定的参考价值。
题意:有n个花瓶,每个花瓶中只能放一朵花。
两种操作,一种是从A开始放F朵花,如果有的花瓶中已经有花则跳过这个花瓶,往下一个花瓶放;
输出这次放的花的左右端点。如果能放但是放不完f朵输出n就好了
第二种是将区间[A,B]之间花瓶中的花清空。输出这次总共清理出了多少支花。
思路:第二种很明显可以用线段树实现,问题在第一种如何用线段树实现
用二分 和 线段树 来判断右端点的位置 这样就可以了 第一次操作就成了区间更新
并且查询左右端点
#include<cstdio> #include<cstring> #include<iostream> #include<vector> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define fi first #define se second const int N = 5E4+3; const int M = 5e4+3; int n,m; int sum[N<<2],fst[N<<2],las[N<<2],L[N<<2],R[N<<2]; int col[N<<2]; //fst 开始空的 las最后空的 sum 空的数量 void pushup(int rt){ sum[rt] = sum[rt<<1]+sum[rt<<1|1]; if(las[rt<<1|1]!=-1) las[rt]=las[rt<<1|1]; else las[rt]=las[rt<<1]; if(fst[rt<<1]!=-1) fst[rt]=fst[rt<<1]; else fst[rt] = fst[rt<<1|1]; R[rt] = R[rt<<1|1]; L[rt] = L[rt<<1]; } void pushdown(int rt){ //添加 if(col[rt]==1){ col[rt<<1]=col[rt<<1|1] = col[rt]; sum[rt<<1] = 0; sum[rt<<1|1] = 0; las[rt<<1]=las[rt<<1|1] = -1; fst[rt<<1]=fst[rt<<1|1] =-1; col[rt]=0; } else if(col[rt]==-1){ col[rt<<1]=col[rt<<1|1] = col[rt]; sum[rt<<1] = R[rt<<1]-L[rt<<1]+1; sum[rt<<1|1] = R[rt<<1|1]-L[rt<<1|1]+1; las[rt<<1] = R[rt<<1]; fst[rt<<1] = L[rt<<1]; las[rt<<1|1] = R[rt<<1|1]; fst[rt<<1|1] = L[rt<<1|1]; col[rt]=0; } } void build(int l,int r,int rt){ col[rt] =0; if(l==r){ L[rt] = r; R[rt] = l; sum[rt]=1; las[rt]=r; fst[rt]=l; return ; } int mid = (l+r)/2; build(lson);build(rson); pushup(rt); } void update(int l,int r,int rt, int a,int b,int val){ if(a<=l && b>=r){ if(val==1){ if(sum[rt] ==0)return; col[rt] = val; sum[rt] = 0; las[rt]=fst[rt]=-1; } else if(val==-1){ if(sum[rt]==R[rt]-L[rt]+1)return; // printf("%d %d %d %d %d %d ",l,r,rt,a,b,sum[rt]); col[rt]=val; sum[rt]= R[rt]-L[rt]+1; las[rt]=R[rt]; fst[rt]=L[rt]; // printf("gai: %d %d %d %d %d %d ",l,r,rt,a,b,sum[rt]); } return ; } pushdown(rt); int mid=(l+r)/2; if( a<=mid ) update(lson,a,b,val); if( b>mid ) update(rson ,a,b,val); pushup( rt ); } int qfst(int l,int r,int rt,int a,int b){ if(a<=l && b>=r){ return fst[rt]; } pushdown(rt); int mid =(l+r)/2; if(b<=mid)return qfst(lson,a,b); else if( a>mid )return qfst(rson,a,b); else { int ans1=-1; if(a<=mid) ans1 = qfst(lson,a,b); if(ans1!=-1)return ans1; if(b>mid) return qfst(rson,a,b); } } int qlst(int l,int r,int rt,int a,int b){ if(a<=l && b>=r){ return las[rt]; } pushdown(rt); int mid =(l+r)/2; if(b<=mid)return qlst(lson,a,b); else if(a>mid)return qlst(rson,a,b); else { int ans1=-1; if(b>mid) ans1= qlst(rson,a,b); if(ans1!=-1)return ans1; if(a<=mid)return qlst(lson,a,b); } } int qnum(int l,int r,int rt,int a,int b){ if(a<=l && b>=r){ //printf("get :%d %d %d %d %d %d ",l,r,rt,a,b,sum[rt]); int res = sum[rt]; return res; } pushdown(rt); int ans = 0; int mid =(l+r)/2; if(a<=mid) ans+=qnum(lson,a,b); if(b>mid) ans+=qnum(rson,a,b); return ans; } int b_s(int st,int need){ int l=st,r=n; int res = qnum(1,n,1,st,n); if(res==0)return -1; if(res<need)return n; int ans = n; while(l<=r){ int m = (l+r)/2; if(qnum(1,n,1,st,m)>=need){ ans = min(ans,m); r=m-1; } else l= m+1; } return ans; } int main(){ int t; cin>>t; int op; while(t--){ scanf("%d %d",&n,&m); build(1,n,1); while(m--){ scanf("%d",&op); if(op==1){ int x,f;scanf("%d %d",&x,&f); x++; int v = b_s(x,f); if(v==-1){ printf("Can not put any one. "); } else { printf("%d %d ",qfst(1,n,1,x,v)-1 ,qlst(1,n,1,x,v)-1); update(1,n,1,x,v,1); } } else if(op==2){ int a,b;scanf("%d %d",&a,&b); a++;b++; int res = qnum(1,n,1,a,b); printf("%d ",b-a+1-res); update(1,n,1,a,b,-1); // cout<<sum[24]<<"!!"<<endl; res = qnum(1,n,1,a,b); // printf("update : %d ",b-a+1-res); } } cout<<endl; } return 0; }
以上是关于hdu 4614 线段树 二分的主要内容,如果未能解决你的问题,请参考以下文章
HDU4614Vases and Flowers 二分+线段树;
HDU 4614 Vases and Flowers 线段树+二分
Vases and Flowers HDU - 4614线段树+主席树思维/二分