HDU4614Vases and Flowers 二分+線段樹;
阿新 • • 發佈:2018-05-10
ref Go cto and min span pre tails tdi
參考:https://blog.csdn.net/ophunter_lcm/article/details/9879495
題意:
有n個花瓶,有兩種操作,1.從a開始放b朵花,有花的花瓶跳過,2.把a到b間的花全部拿下來。
思路:
線段樹+二分
利用二分確定區間,這樣就可以是線段樹實現更簡單的問題:
1)對區間進行全部設置為1的操作
2)對區間進行全部清零的操作
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include<string> #include <vector> #include <map> #include <set> #include <queue> #include <list> #include <iterator> using namespace std; #define lson l , mid , rt << 1 #define rson mid + 1 , r , rt << 1 | 1 #define debug(x) cerr << #x << " = " << x << "\n"; typedeflong long ll; const int maxn = 50009; const int mdd = 10007; int n,m; struct node { int l,r; int lazy,sum; }st[maxn<<2]; void build(int l,int r,int rt) { st[rt].l = l,st[rt].r = r; st[rt].sum = 0; st[rt].lazy = -1; int mid = (l+r)>>1; if(l==r)return; build(lson); build(rson); } inlinevoid pushup(int rt) { st[rt].sum = st[rt<<1].sum + st[rt<<1|1].sum; } inline void pushdown(int rt) { if(st[rt].lazy==1) { st[rt<<1].lazy = st[rt<<1|1].lazy = st[rt].lazy; st[rt<<1].sum = st[rt<<1].r - st[rt<<1].l + 1; st[rt<<1|1].sum = st[rt<<1|1].r - st[rt<<1|1].l + 1; } else if(st[rt].lazy==0) { st[rt<<1].lazy = st[rt<<1|1].lazy = st[rt].lazy; st[rt<<1].sum = st[rt<<1|1].sum = 0; } st[rt].lazy = -1; } int query(int l,int r,int rt,int L,int R) { if(l>=L&&r<=R) { return st[rt].sum; } int mid = (l + r)>>1; pushdown(rt); int ans = 0; if(mid>=L)ans += query(l,mid,rt<<1,L,R); if(mid<R)ans += query(mid+1,r,rt<<1|1,L,R); return ans; } void update(int l,int r,int rt,int L,int R,int op) { if(l>=L&&r<=R) { if(op==1){ st[rt].lazy = 1; st[rt].sum = r - l + 1; } else { st[rt].lazy = 0; st[rt].sum = 0; } return; } int mid = (r+l)>>1; pushdown(rt); if(mid>=L)update(l,mid,rt<<1,L,R,op); if(mid<R)update(mid+1,r,rt<<1|1,L,R,op); pushup(rt); } int bdfind(int st,int len)//二分查找 { int le = st; int ri = n; int ans = -1; while(le <= ri) { int mid = (le + ri)>>1; int lenSum = query(1,n,1,st,mid); //找有花的瓶子個數 if(lenSum + len == mid - st + 1) { ans = mid; //不要直接return,要找最小的。 ri = mid - 1; } else if(lenSum + len < mid - st +1) { ri = mid - 1; } else le = mid + 1; } return ans;//找到在【st,mid】間符合len個空瓶; } int main(){ // freopen("input","r",stdin); int t; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); build(1,n,1); while(m--) { int op; int a,b,c; scanf("%d%d%d", & op, & a,& b); if(op==1) { a++; int st = bdfind(a,1); if(st==-1) puts("Can not put any one."); else { int tmp = query(1,n,1,st,n); tmp = (n - st + 1) - tmp; //空瓶個數 b = min(tmp,b); int ed = bdfind(a, b); printf("%d %d\n",st-1,ed-1); update(1,n,1,st,ed,1); } } else { a++,b++; printf("%d\n",query(1,n,1,a,b)); update(1,n,1,a,b,0); } } puts(""); } return 0; }
HDU4614Vases and Flowers 二分+線段樹;