hdu 4614 [简单线段树+二分查找]

// hdu 4614

// 题意 机器翻译 爱丽丝非常受欢迎,每天都能收到很多花。她有N个花瓶,编号从0到N-1。当她收到几朵花时,她会尝试将它们放在花瓶中,一朵花放在一个花瓶中。她随机选择花瓶A,并尝试在花瓶中放一朵花。如果花瓶中没有花,她会在上面放一朵花,否则她会跳过这个花瓶。然后她将尝试放入花瓶A + 1,A + 2,...,N-1,直到没有花了,或者她尝试了花瓶N-1。剩下的花将被丢弃。当然,有时她会清洗花瓶。由于花瓶过多,她随机选择清洗编号从A到B(A <= B)的花瓶。清洗过的花瓶中的花将被丢弃。

第一行包含一个整数T,表示测试用例的数量。

  对于每个测试用例,第一行包含两个整数N(1 <N <50001)和M(1 <M <50001)。N是花瓶的数量,M是爱丽丝的业务。接下来的M行中的每行包含三个整数。一行的第一个整数是K(1或2)。如果K为1,则跟随两个整数A和F。这意味着爱丽丝会收到F朵花,然后尝试先在花瓶A中放一朵花。如果K为2,则跟随两个整数A和B。这意味着所有者希望清洗编号从A到B(A <= B)的花瓶。
  对于K为1的每个操作,输出花瓶的位置,爱丽丝将第一朵花和最后一朵花放在花瓶中,并用空格隔开。如果她不能放任何东西,则输出“不能放任何东西”。对于K为2的每个操作,输出丢弃的花朵数量。
  1 /*
  2  * @Promlem: hdu 4614
  3  * @Time Limit: 2000ms
  4  * @Memory Limit: 32768k
  5  * @Author: pupil-XJ
  6  * @Date: 2019-10-12 14:11:16
  7  * @LastEditTime: 2019-10-13 01:03:11
  8  */
  9 #include<cstdio>
 10 #include<algorithm>
 11 #define L k<<1
 12 #define R k<<1|1
 13 #define mid (tree[k].l+tree[k].r)>>1
 14 using namespace std;
 15 const int MAXN = 50000+5;
 16 
 17 struct segmemt_tree {
 18     int l, r;
 19     int num, f;
 20 } tree[4*MAXN+1];
 21 
 22 inline void build(int k, int l, int r) {
 23     tree[k].l = l; tree[k].r = r;
 24     tree[k].num = 0;
 25     tree[k].f = -1;
 26     if(l == r) return ;
 27     int m = mid;
 28     build(L, l, m);
 29     build(R, m+1, r);
 30 }
 31 
 32 inline void push_down(int k) {
 33     tree[L].f = tree[R].f = tree[k].f;
 34     int m = mid;
 35     tree[L].num = (m-tree[k].l+1) * tree[k].f;
 36     tree[R].num = (tree[k].r-m) * tree[k].f;
 37     tree[k].f = -1;
 38 }
 39 
 40 inline int query(int k, int x, int y) {// 查询区间内插入花的数量
 41     if(tree[k].l >= x && tree[k].r <= y) return tree[k].num;
 42     if(tree[k].f != -1) push_down(k);
 43     int m = mid;
 44     int ans = 0;
 45     if(x <= m) ans = query(L, x, y);
 46     if(y > m) ans += query(R, x, y);
 47     return ans;
 48 }
 49 
 50 inline int bin(int start, int end, int cnt) {// 二分查找 l=start 到 r=end 第cnt个空花瓶
 51     int l = start, r = end;
 52     while(l < r) {
 53         int m = (l + r) / 2;
 54         int t = (m - start + 1) - query(1, start, m);
 55         if(t >= cnt) r = m;
 56         else l = m + 1;
 57     }
 58     return l;
 59 }
 60 
 61 inline void change(int k, int x, int y, int v) {
 62     if(tree[k].l >= x && tree[k].r <= y) {
 63         tree[k].f = v;
 64         tree[k].num = (tree[k].r - tree[k].l + 1) * v;
 65         return ;
 66     }
 67     if(tree[k].f != -1) push_down(k);
 68     int m = mid;
 69     if(x <= m) change(L, x, y, v);
 70     if(y > m) change(R, x, y, v);
 71     tree[k].num = tree[L].num + tree[R].num;
 72 }
 73 
 74 int main() {
 75     int T;
 76     scanf("%d", &T);
 77     while(T--) {
 78         int n, m;
 79         scanf("%d%d", &n, &m);
 80         build(1, 0, n-1);
 81         int op, x, y;
 82         int s, e;
 83         for(int i = 0; i != m; ++i) {
 84             scanf("%d%d%d", &op, &x, &y);
 85             if(op == 1) {
 86                 int one = query(1, x, n-1);
 87                 if(one == n-1-x+1) printf("Can not put any one.
");
 88                 else {
 89                     s = bin(x, n-1, 1);// 第一个空花瓶位置
 90                     e = bin(s, n-1, min(n-1-x+1-one, y));// 最后一个空花瓶位置
 91                     printf("%d %d
", s, e);
 92                     change(1, s, e, 1);
 93                 }
 94             }
 95             else printf("%d
", query(1, x, y)), change(1, x, y, 0);
 96         }
 97         printf("
");
 98     }
 99     return 0;
100 }

附上一个很蠢的代码 TLE

 1 /*
 2  * @Promlem: 
 3  * @Time Limit: ms
 4  * @Memory Limit: k
 5  * @Author: pupil-XJ
 6  * @Date: 2019-10-12 14:11:16
 7  * @LastEditTime: 2019-10-12 22:58:36
 8  */
 9 #include<cstdio>
10 #define L k<<1
11 #define R k<<1|1
12 #define mid (tree[k].l+tree[k].r)>>1
13 using namespace std;
14 const int MAXN = 50000+4;
15 
16 struct segmemt_tree {
17     int l, r, num;
18     int f;
19 } tree[4*MAXN+1];
20 
21 void build(int k, int l, int r) {
22     tree[k].l = l; tree[k].r = r;
23     tree[k].num = 0;
24     tree[k].f = 0;
25     if(l == r) return ;
26     int m = mid;
27     build(L, l, m);
28     build(R, m+1, r);
29 }
30 
31 void down(int k) {
32     tree[L].num = tree[R].num = 0;
33     tree[L].f = tree[R].f = 1;
34     tree[k].f = 0;
35 }
36 
37 int sx, ex, sum;
38 void update(int k, int x, int y, int op) {
39     if(op == 1 && !sum) return ;
40     // if(tree[k].num == tree[k].r-tree[k].l+1) return ;
41     if(tree[k].l >= x && tree[k].r <= y) {
42         if(tree[k].f) down(k);
43         if(op == 0) {
44             tree[k].f = 1;
45             sum += tree[k].num;
46             tree[k].num = 0;
47         }
48         else if(tree[k].l == tree[k].r) {
49             if(tree[k].num == 0) {
50                 tree[k].num = 1;
51                 if(sx == -1) sx = ex = tree[k].l;
52                 else ex = tree[k].l;
53                 --sum;
54             }
55         }
56         else {
57             int m = mid;
58             if(x <= x) update(L, x, y, op);
59             if(y > m) update(R, x, y, op);
60             tree[k].num = tree[L].num + tree[R].num;
61         }
62         return ;
63     }
64     if(tree[k].f) down(k);
65     int m = mid;
66     if(x <= m) update(L, x, y, op);
67     if(y > m) update(R, x, y, op);
68     tree[k].num = tree[L].num + tree[R].num;
69 }
70 
71 int main() {
72     int T;
73     scanf("%d", &T);
74     while(T--) {
75         int n, m;
76         scanf("%d%d", &n, &m);
77         build(1, 0, n-1);
78         int op, x, y;
79         for(int i = 0; i != m; ++i) {
80             scanf("%d%d%d", &op, &x, &y);
81             if(op == 1) {
82                 sx = ex = -1;
83                 sum = y;
84                 update(1, x, n-1, 1);
85                 if(ex == -1) printf("Can not put any one.
");
86                 else printf("%d %d
", sx, ex);
87             }
88             else sum = 0, update(1, x, y, 0), printf("%d
", sum);
89         }
90         printf("
");
91     }
92     return 0;
93 }
TLE
原文地址:https://www.cnblogs.com/pupil-xj/p/11664604.html