HDU - 4614 【二分+线段树维护】

Vases and Flowers

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

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

3 7

2

1 9

4

Can not put any one.

2 6

2

0 9

4

4 5

2 3

题意:

操作1:从x位置往后插y枝花,前提是只能给空花瓶插,并求出最左边和最右边插花的位置。

操作2:求[x, y]内有多少只花,并清空区间内的花瓶。

题解:

因为每个花瓶只能插一枝花,所以用区间和可以判断能插几只花。

对于操作1,我们可以判断[x, n]的空花瓶数cnt,如果为0,直接GG;否则看它能插最多y枝花还是cnt枝花。

通过二分可以找到这个l, r的位置;

对于操作2,就是区间求和,区间更新,裸的。

代码:

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <bitset>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <cmath>
 10 #include <list>
 11 #include <set>
 12 #include <map>
 13 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 14 #define per(i,a,b) for(int i = a;i >= b;-- i)
 15 #define mem(a,b) memset((a),(b),sizeof((a)))
 16 #define FIN freopen("in.txt","r",stdin)
 17 #define FOUT freopen("out.txt","w",stdout)
 18 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 19 #define mid ((l+r)>>1)
 20 #define ls (id<<1)
 21 #define rs ((id<<1)|1)
 22 using namespace std;
 23 typedef long long LL;
 24 typedef pair<int, int> PIR;
 25 const int N = 50005;
 26 struct Node{
 27     int sum, lazy;
 28 }node[N*4];
 29 int T, n, m, op, x, y;
 30
 31 void pushUp(int id, int l, int r){
 32     node[id].sum = node[ls].sum+node[rs].sum;
 33 }
 34 void pushDown(int id, int l, int r){
 35     node[ls].sum = node[id].lazy*(mid-l+1);
 36     node[rs].sum = node[id].lazy*(r-mid);
 37     node[ls].lazy = node[id].lazy;
 38     node[rs].lazy = node[id].lazy;
 39     node[id].lazy = -1;
 40 }
 41 void build(int id, int l, int r){
 42     node[id].lazy = -1;
 43     if(l == r){
 44         node[id].sum = 0;
 45         return ;
 46     }
 47     build(ls, l, mid);
 48     build(rs, mid+1, r);
 49     pushUp(id, l, r);
 50 }
 51 void update(int id, int l, int r, int ql, int qr, int p){
 52     if(l == ql && r == qr){
 53         node[id].lazy = p;
 54         node[id].sum = (r-l+1)*p;
 55         return ;
 56     }
 57     if(node[id].lazy != -1)
 58         pushDown(id, l, r);
 59     if(qr <= mid)   update(ls, l, mid, ql, qr, p);
 60     else if(ql > mid)
 61         update(rs, mid+1, r, ql, qr, p);
 62     else{
 63         update(ls, l, mid, ql, mid, p);
 64         update(rs, mid+1, r, mid+1, qr, p);
 65     }
 66     pushUp(id, l, r);
 67 }
 68 int query(int id, int l, int r, int ql, int qr){
 69     if(l == ql && r == qr){
 70         return node[id].sum;
 71     }
 72     if(node[id].lazy != -1)   pushDown(id, l, r);
 73     if(qr <= mid)   return query(ls, l, mid, ql, qr);
 74     else if(ql > mid)
 75         return query(rs, mid+1, r, ql, qr);
 76     else{
 77         return query(ls, l, mid, ql, mid)+query(rs, mid+1, r, mid+1, qr);
 78     }
 79 }
 80 int main()
 81 {IO;
 82     //FIN;
 83     cin >> T;
 84     while(T--){
 85         cin >> n >> m;
 86         build(1, 1, n);
 87         rep(i, 1, m){
 88             cin >> op >> x >> y;
 89             if(op == 1){
 90                 x++;
 91                 int cnt = n-x+1-query(1, 1, n, x, n);
 92                 if(cnt == 0){
 93                     cout << "Can not put any one." << endl;
 94                     continue;
 95                 }
 96                 cnt = min(cnt, y);
 97                 int low = x, high = n, ansl, ansr;
 98                 while(low <= high){
 99                     int md = (low+high)>>1;
100                     if(query(1, 1, n, x, md) < md-x+1){
101                         ansl = md;
102                         high = md-1;
103                     }
104                     else{
105                         low = md+1;
106                     }
107                 }
108                 low = x, high = n;
109                 while(low <= high){
110                     int md = (low+high)>>1;
111                     if(md-x+1-query(1, 1, n, x, md) >= cnt){
112                         ansr = md;
113                         high = md-1;
114                     }
115                     else{
116                         low = md+1;
117                     }
118                 }
119                 update(1, 1, n, ansl, ansr, 1);
120                 cout << ansl-1 << " " << ansr-1 << endl;
121             }
122             else{
123                 x++;
124                 y++;
125                 int ans = query(1, 1, n, x, y);
126                 update(1, 1, n, x, y, 0);
127                 cout << ans << endl;
128             }
129         }
130         cout << endl;
131     }
132     return 0;
133 }

Author

时间: 2024-10-20 09:15:13

HDU - 4614 【二分+线段树维护】的相关文章

zoj 3888 Twelves Monkeys 二分+线段树维护次小值

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3888 Twelves Monkeys Time Limit: 5 Seconds      Memory Limit: 32768 KB James Cole is a convicted criminal living beneath a post-apocalyptic Philadelphia. Many years ago, the Earth's surf

HDU 5068 Harry And Math Teacher( 矩阵乘法 + 线段树维护 )

HDU 5068 Harry And Math Teacher( 矩阵乘法 + 线段树维护 ) 题意: 首先是这题题意理解错误,,其次是这题无法理解状态... 已经不是英文有多烂的情况了,是中文没学好啊.....大学不学语文才是真正的硬伤啊 题目意思 有一个城堡有很多层楼, 每层楼有2个门,每个门里面又有两个楼梯,可以通往上一层的两个门 问,从x层楼到y层楼有多少中方法(不能返回) 具体看图吧,,,已经不会说话了 1 #include <cstdio> 2 #include <cstri

Codeforces 460C 二分结果+线段树维护

发现最近碰到好多次二分结果的题目,上次多校也是,被我很机智的快速过了,这个思想确实非常不错.在正面求比较难处理的时候,二分结果再判断是否有效往往柳暗花明. 这个题目给定n个数字的序列,可以操作m次,每次要操作w个连续的数字,每次的操作将使得该段连续数字的数都+1,最后求整个序列最小值的最大值 求最小值最大,明显的二分结果的题目,我一开始还是在ACdream那个群里看到这个题,说是二分+线段树的题目,我就来做了一下..首先二分部分很容易,下界就是初始序列的最小值,上界就是 下界+m,至于怎么判断这

BZOJ 2402 陶陶的难题II 二分答案+斜率优化+树链剖分+线段树维护凸包

题目大意:给定一棵树,每个点有两个坐标(x1,y1)和(x2,y2),多次询问某条链上选择两个点i和j(可以相同),求(y1i+y2j)/(x1i+x2j)的最大值 我竟没看出来这是01分数规划...真是老了... 二分答案ans,问题转化成验证(y1i+y2j)/(x1i+x2j)是否>=ans 将式子变形可得(y1i-ans*x1i)+(y2j-ans*x2j)>=0 加号两边独立,分别计算即可 问题转化为求链上y-ans*x最大的点 令P=y-ans*x 则y=ans*x+P 我们发现这

HDU 6155 Subsequence Count 线段树维护矩阵

Subsequence Count Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others) Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries on the string. There are two types of querie

hdu 4037 Development Value(线段树维护数学公式)

Development Value Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 609    Accepted Submission(s): 118 Problem Description StarCraft 2 (SC2) is a famous game. More and more people fall in love wi

HDU 2795 Billboard (线段树+贪心)

手动博客搬家:本文发表于20170822 21:30:17, 原地址https://blog.csdn.net/suncongbo/article/details/77488127 URL: http://acm.hdu.edu.cn/showproblem.php?pid=2795题目大意:有一个h*w的木板 (h, w<=1e9), 现在有n (n<=2e5)张1*xi的海报要贴在木板上,按1~n的顺序每次贴海报时会选择最上的一排的最左边贴 (海报不能互相覆盖), 求每张海报会被贴在哪一行

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

计蒜客16492 building(二分线段树/分块)

题解: 考虑用线段树维护楼的最大值,然后这个问题就很简单了. 每次可以向左二分出比x高的第一个楼a,同理也可以向右二分出另一个楼b,如果a,b都存在,答案就是b-a-1. 注意到二分是可以直接在线段树上进行的,所以复杂度是O(nlogn). 当然这里是用分块做的,更暴力一些. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace st