hdu 4614 線段樹 二分
阿新 • • 發佈:2018-10-25
但是 操作 tdi 清理 scan 線段 string class b-
題意:有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\n",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\n",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\n",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.\n"); } else { printf("%d %d\n",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\n",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\n",b-a+1-res); } } cout<<endl; } return 0; }
hdu 4614 線段樹 二分