题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614
题意:
给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花。
然后有2个操作。
1)a b 往在a位置后面(包括a)插b朵花,输出插入的首位置和末位置。
2)a b 输出区间[a , b ]范围内的花的数量,然后全部清空。
操作看起来挺简单的但写起来还是有点复杂的
首先建树的时候可以设置变量first与ends分别表示一个区间最先出现的0和最后出现的0,sum=0
表示没放东西,sum=1表示放了。我们可以用二分来查找插完b朵花后的结尾区间。然后在寻找这个
区间的first与ends值之后就简单了。
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int M = 5e4 + 10; struct TnT { int l , r , num , add , first , ends; }T[M << 2]; int n , m; void build(int l , int r , int p) { int mid = (l + r) >> 1; T[p].l = l , T[p].r = r , T[p].add = T[p].num = 0 , T[p].first = l , T[p].ends = r; if(l == r) { return ; } build(l , mid , p << 1); build(mid + 1 , r , (p << 1) | 1); } void pushup(int p) { T[p].num = T[p << 1].num + T[(p << 1) | 1].num; if(T[p << 1].first == -1) { T[p].first = T[(p << 1) | 1].first; } else if(T[(p << 1) | 1].first == -1) { T[p].first = T[p << 1].first; } else { T[p].first = min(T[(p << 1) | 1].first , T[p << 1].first); } if(T[(p << 1) | 1].ends == -1) { T[p].ends = T[(p << 1) | 1].ends; } else if(T[(p << 1) | 1].ends == -1) { T[p].ends = T[p << 1].ends; } else { T[p].ends = max(T[(p << 1) | 1].ends , T[p << 1].ends); } } void pushdown(int p) { if(T[p].add == 1) { T[p << 1].num = T[p << 1].r - T[p << 1].l + 1; T[p << 1].first = -1; T[p << 1].ends = -1; T[(p << 1) | 1].num = T[(p << 1) | 1].r - T[(p << 1) | 1].l + 1; T[(p << 1) | 1].first = -1; T[(p << 1) | 1].ends = -1; T[p << 1].add = T[p].add; T[(p << 1) | 1].add = T[p].add; } if(T[p].add == -1) { T[p << 1].first = T[p << 1].l; T[p << 1].ends = T[p << 1].r; T[p << 1].num = 0; T[(p << 1) | 1].num = 0; T[p << 1].add = T[p].add; T[(p << 1) | 1].first = T[(p << 1) | 1].l; T[(p << 1) | 1].ends = T[(p << 1) | 1].r; T[(p << 1) | 1].add = T[p].add; } T[p].add = 0; } int query(int l , int r , int p) { int mid = (T[p].l + T[p].r) >> 1; if(T[p].l == l && T[p].r == r) { return T[p].num; } pushdown(p); if(mid >= r) { return query(l , r , p << 1); } else if(mid < l) { return query(l , r , (p << 1) | 1); } else { return query(l , mid , p << 1) + query(mid + 1 , r , (p << 1) | 1); } } int queryfr(int l , int r , int p) { int mid = (T[p].l + T[p].r) >> 1; if(T[p].l == l && T[p].r == r) { return T[p].first; } pushdown(p); if(mid >= r) { return queryfr(l , r , p << 1); } else if(mid < l) { return queryfr(l , r , (p << 1) | 1); } else { int ans = queryfr(l , mid , p << 1); if(ans == -1) { return queryfr(mid + 1 , r , (p << 1) | 1); } else { return ans; } } } int queryed(int l , int r , int p) { int mid = (T[p].l + T[p].l) >> 1; if(T[p].l == l && T[p].r == r) { return T[p].ends; } pushdown(p); if(mid >= r) { return queryed(l , r , p << 1); } else if(mid < l) { return queryed(l , r , (p << 1) | 1); } else { int ans = queryed(mid + 1 , r , (p << 1) | 1); if(ans == -1) { return queryed(l , mid , p << 1); } else { return ans; } } } void updata(int l , int r , int p , int ad) { int mid = (T[p].l + T[p].r) >> 1; if(T[p].l == l && T[p].r == r) { if(ad == 1) { T[p].add = 1; T[p].num = T[p].r - T[p].l + 1; T[p].first = -1; T[p].ends = -1; return ; } if(ad == -1) { T[p].add = -1; T[p].num = 0; T[p].first = T[p].l; T[p].ends = T[p].r; return ; } } pushdown(p); if(mid >= r) { updata(l , r , p << 1 , ad); } else if(mid < l) { updata(l , r , (p << 1) | 1 , ad); } else { updata(l , mid , p << 1 , ad); updata(mid + 1 , r , (p << 1) | 1 , ad); } pushup(p); } int bisearch(int sta , int sum) { int l = sta , r = n; int ans = n; while(l <= r) { int mid = (l + r) >> 1; int gg = query(sta , mid , 1); gg = mid - sta + 1 - gg; if(gg >= sum) { r = mid - 1; ans = mid; } else { l = mid + 1; } } return ans; } int main() { int t; scanf("%d" , &t); while(t--) { scanf("%d%d" , &n , &m); build(1 , n , 1); for(int i = 1 ; i <= m ; i++) { int k , a , f; scanf("%d%d%d" , &k , &a , &f); if(k == 1) { a++; int res = query(a , n , 1); res = n - a + 1 - res; if(res == 0) { printf("Can not put any one. "); continue; } int sum = min(res , f); int ed = bisearch(a , sum); int fr = queryfr(a , ed , 1); updata(fr , ed , 1 , 1); printf("%d %d " , fr - 1 , ed - 1); } if(k == 2) { a++ , f++; int res = query(a , f , 1); updata(a , f , 1 , -1); printf("%d " , res); } } printf(" "); } return 0; }