1. 程式人生 > >HDU 4614 Vases and Flowers 線段樹+二分

HDU 4614 Vases and Flowers 線段樹+二分

too others tput sometimes 標記傳遞 scan mean 二分 set

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4614

題意:N個花瓶,兩種操作。

操作1:從第a個花瓶開始放花,放最多f個,如果花瓶已經有花就跳過,直到放完,或者無更多花瓶,要求輸出這次放花的第一個位置和最後一個位置,如果沒放就輸出Cannot。。。

操作2:將花瓶a到b區間內的花都扔了,然後輸出扔掉的花的數目。

解題思路:花瓶有花為0,無花為1,那麽實際上這是一個區間更新以及求和,求左右端點的問題。線段樹節點維護一個 sum--區間和,lid--最左端為1的點,rid--最右端為1的點。對於操作1,首先找到放的區間。即如果能放這麽多花,最後一個可以放的位置在哪。當然如果不能放花則直接輸出cannot。。。 如果能放的比要放的少就是從a到n,否則二分查找以a為起點的空花瓶個數為要放的花的數目f的位置,查詢,更新就行。

理清思路的話,不算難,就是過程略復雜。

順便說下這幾天做線段樹對延遲標記的理解:延遲標記的作用不用多說,要註意的是更新到一個區間時,如果包含了整個區間的話,就加上延遲標記,同時要更新整個區間的值。如果需要往左右孩子更新的話,那麽就將延遲標記傳遞給左右孩子,同時更新他們節點的值。所以,對於延遲標記來講,一個要求就是能直接計算出它所帶來的屬性值的變化。

代碼:

  1 const int maxn = 5e4 + 5;
  2 struct node{
  3     int sum, lazy;
  4     int lid, rid;
  5 };
  6 node tree[maxn * 4
]; 7 int n, m; 8 9 10 void build(int l, int r, int k){ 11 tree[k].sum = (r - l + 1);tree[k].lazy = 0; 12 tree[k].lid = l; tree[k].rid = r; 13 if(l == r) return; 14 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 15 build(l, mid, lc); 16 build(mid + 1
, r, rc); 17 } 18 void pushdown(int l, int r, int k){ 19 if(tree[k].lazy == 0) return; 20 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 21 if(tree[k].lazy == 1){ 22 tree[lc].lazy = 1; tree[rc].lazy = 1; 23 tree[lc].sum = (mid - l + 1); tree[lc].lid = l; tree[lc].rid = mid; 24 tree[rc].sum = (r - mid); tree[rc].lid = mid + 1; tree[rc].rid = r; 25 } 26 else if(tree[k].lazy == -1){ 27 tree[lc].lazy = -1; tree[rc].lazy = -1; 28 tree[lc].sum = 0; tree[lc].lid = 0; tree[lc].rid = 0; 29 tree[rc].sum = 0; tree[rc].lid = 0; tree[rc].rid = 0; 30 } 31 tree[k].lazy = 0; 32 } 33 void pushup(int l, int r, int k){ 34 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 35 tree[k].sum = tree[lc].sum + tree[rc].sum; 36 if(tree[lc].lid != 0) tree[k].lid = tree[lc].lid; 37 else if(tree[rc].lid != 0) tree[k].lid = tree[rc].lid; 38 else tree[k].lid = 0; 39 if(tree[rc].rid != 0) tree[k].rid = tree[rc].rid; 40 else if(tree[lc].rid != 0) tree[k].rid = tree[lc].rid; 41 else tree[k].rid = 0; 42 } 43 void update(int ul, int ur, int x, int l, int r, int k){ 44 if(ul <= l && ur >= r){ 45 tree[k].lazy = x; 46 if(x == 1){ 47 tree[k].sum = (r - l + 1); 48 tree[k].lid = l; tree[k].rid = r; 49 } 50 else if(x == -1){ 51 tree[k].sum = 0; 52 tree[k].lid = tree[k].rid = 0; 53 } 54 return; 55 } 56 if(ul > r || ur < l) return; 57 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 58 pushdown(l, r, k); 59 update(ul, ur, x, l, mid, lc); 60 update(ul, ur, x, mid + 1, r, rc); 61 pushup(l, r, k); 62 } 63 int query_left(int ql, int qr, int l, int r, int k){ 64 if(ql <= l && qr >= r){ 65 return tree[k].lid; 66 } 67 if(ql > r || qr < l) return 0; 68 pushdown(l, r, k); 69 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 70 int q1 = query_left(ql, qr, l, mid, lc); 71 int q2 = query_left(ql, qr, mid + 1, r, rc); 72 if(q1 == 0) return q2; 73 return q1; 74 } 75 int query_right(int ql, int qr, int l, int r, int k){ 76 if(ql <= l && qr >= r){ 77 return tree[k].rid; 78 } 79 if(ql > r || qr < l) return 0; 80 pushdown(l, r, k); 81 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 82 int q1 = query_right(ql, qr, l, mid, lc); 83 int q2 = query_right(ql, qr, mid + 1, r, rc); 84 if(q2 == 0) return q1; 85 return q2; 86 } 87 int sum(int sl, int sr, int l, int r, int k){ 88 if(sl <= l && sr >= r){ 89 return tree[k].sum; 90 } 91 if(sl > r || sr < l) return 0; 92 pushdown(l, r, k); 93 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 94 return sum(sl, sr, l, mid, lc) + sum(sl, sr, mid + 1, r, rc); 95 } 96 int check(int u, int f){ 97 int tmp = sum(u, n, 1, n, 1); 98 if(tmp == 0) return -1; 99 else if(tmp <= f) return n; 100 int l = u, r = n; 101 while(l < r){ 102 int mid = (l + r) >> 1; 103 tmp = sum(u, mid, 1, n, 1); 104 if(tmp >= f) r = mid; 105 else l = mid + 1; 106 } 107 return l; 108 } 109 110 int main(){ 111 int T; 112 scanf("%d", &T); 113 while(T--){ 114 memset(tree, 0, sizeof(tree)); 115 scanf("%d %d", &n, &m); 116 build(1, n, 1); 117 while(m--){ 118 int k, a, b; 119 scanf("%d %d %d", &k, &a, &b); 120 if(k == 1){ 121 a++; 122 int tmp = check(a, b); 123 if(tmp == -1) { 124 puts("Can not put any one."); 125 continue; 126 } 127 int u = query_left(a, tmp, 1, n, 1); 128 int v = query_right(a, tmp, 1, n, 1); 129 printf("%d %d\n", u - 1, v - 1); 130 update(a, tmp, -1, 1, n, 1); 131 } 132 else{ 133 a++;b++; 134 int u = b - a + 1 - sum(a, b, 1, n, 1); 135 printf("%d\n", u); 136 update(a, b, 1, 1, n, 1); 137 } 138 } 139 puts(""); 140 } 141 }

題目:

Vases and Flowers

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3574 Accepted Submission(s): 1460


Problem Description   Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A and try to put a flower in the vase. If the there is no flower in the vase, she will put a flower in it, otherwise she skip this vase. And then she will try put in the vase A+1, A+2, ..., N-1, until there is no flower left or she has tried the vase N-1. The left flowers will be discarded. Of course, sometimes she will clean the vases. Because there are too many vases, she randomly choose to clean the vases numbered from A to B(A <= B). The flowers in the cleaned vases will be discarded.

Input   The first line contains an integer T, indicating the number of test cases.
  For each test case, the first line contains two integers N(1 < N < 50001) and M(1 < M < 50001). N is the number of vases, and M is the operations of Alice. Each of the next M lines contains three integers. The first integer of one line is K(1 or 2). If K is 1, then two integers A and F follow. It means Alice receive F flowers and try to put a flower in the vase A first. If K is 2, then two integers A and B follow. It means the owner would like to clean the vases numbered from A to B(A <= B).

Output   For each operation of which K is 1, output the position of the vase in which Alice put the first flower and last one, separated by a blank. If she can not put any one, then output ‘Can not put any one.‘. For each operation of which K is 2, output the number of discarded flowers.
  Output one blank line after each test case.

Sample Input 2 10 5 1 3 5 2 4 5 1 1 8 2 3 6 1 8 8 10 6 1 2 5 2 3 4 1 0 8 2 2 5 1 4 4 1 2 3

Sample Output [pre]3 7 2 1 9 4 Can not put any one. 2 6 2 0 9 4 4 5 2 3 [/pre]

Author SYSU

Source 2013 Multi-University Training Contest 2

HDU 4614 Vases and Flowers 線段樹+二分