HDU 4614 Vases and Flowers 线段树+二分

题目链接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

时间: 2024-08-24 10:31:46

HDU 4614 Vases and Flowers 线段树+二分的相关文章

hdu 4614 Vases and Flowers

http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意:有N个花瓶,标号为0-N-1,往每一个花瓶放一朵花,然后有M个操作,输入a,b,c,如果a==1表示从b开始放花,期间有花就跳过,直到结束,如果没有放入一朵花,则输出“Can not put any one.”,否则输入第一朵花放的位置和最后一朵花放的位置. 如果a==2 则输出拔掉的花的朵数. 1 #include <cstdio> 2 #include <cstring> 3 #

HDU 4614 Vases and Flowers(线段树区间更新+二分)

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 a

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

hdu 5592 ZYB&#39;s Premutation (线段树+二分查找)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=5592 Problem Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to  restore the premutation.Pair (i,j)(i<j) is considered as a reverse

HDOJ 4614 Vases and Flowers

线段树+二分区间 用线段树维护某一段内还有多少个花瓶可以用,二分确定插入的左右界..... Vases and Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1782    Accepted Submission(s): 700 Problem Description Alice is so popular that

hdu 2852 KiKi&#39;s K-Number (线段树)

hdu 2852 题意: 一个容器,三种操作: (1) 加入一个数 e (2) 删除一个数 e,如果不存在则输出 No Elment! (3) 查询比a大的数中的第k小数,不存在就输出 Not Find! 解法: 关于第三点,可以先查询小于等于a的数的个数cnt,然后直接查询第cnt+k小数就行了 . 二分+树状数组 或者 主席树(有点杀鸡用牛刀的感觉 ...) 也是可以做的  _(:з」∠)_ code:线段树 1 #include <iostream> 2 #include <cst

hdu 1754 I Hate It 线段树 点修改

// hdu 1754 I Hate It 线段树 点修改 // // 不多说,裸的点修改 // // 继续练 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #i

HDU 4902 Nice boat(线段树 区间更新)

Nice boat 大意:给你一个区间,每次可以进行两种操作,1:把区间中的数全都变成x  2:把区间中大于x的数变成gcd(a[i], x),最后输出序列. 思路:线段树成段更行,用num数组的叶子存储数据,节点当作lazy来使用. 1 #include <stdio.h> 2 const int maxn = 100005; 3 4 int num[maxn<<2]; 5 6 int gcd(int a, int b){ 7 return b?gcd(b, a%b):a; 8

hdu 4893 Wow! Such Sequence!(线段树)

题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 修改k的为值增加d 2 l r, 查询l到r的区间和 3 l r, 间l到r区间上的所以数变成最近的斐波那契数,相等的话取向下取. 解题思路:线段树,对于每个节点新增一个bool表示该节点以下的位置是否都是斐波那契数. #include <cstdio> #include <cstring> #include <cstdlib> #include <algor