# HDU - Vases and Flowers(线段树&二分)

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)

## 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.

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

## Problem solving report:

Description: 现在有N个花瓶，一开始每个花瓶都是空的，现在有两种操作：
①1 x y，表示以x号花瓶作为起点，让我们往右插y朵花，遇到空瓶子就放一朵花进去，直到花朵放完或没有瓶子。输出第一个插花的位置，和最后一个插花的位置。
②2 x y，让我们先输出从x到y号花瓶中，一共有多少朵花，然后再清空所有花瓶。
Problem solving: 对于第二种操作，我们直接区间查询然后区间更新即可。对于第一种操作：
①我们首先二分出第一个插花的位子;
②然后再二分最后一个插花的位子即可。

Accepted Code:

/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
#define lson rt << 1
#define rson rt << 1 | 1
const int MAXN = 5e4 + 5;

//线段树维护值
struct Tree {
int val, laz;
}seg[MAXN << 2];

//建树
void Create(int l, int r, int rt) {
seg[rt].val = 0;
seg[rt].laz = -1;
if (!(r - l))
return ;
int mid = l + (r - l >> 1);
Create(l, mid, lson);
Create(mid + 1, r, rson);
}

//上推
void PushUp(int rt) {
seg[rt].val = seg[lson].val + seg[rson].val;
}

//下压
void PushDown(int l, int r, int rt) {
if (~seg[rt].laz) {
int mid = l + (r - l >> 1);
seg[lson].laz = seg[rson].laz = seg[rt].laz;
seg[lson].val = (mid - l + 1) * seg[rt].laz;
seg[rson].val = (r - mid) * seg[rt].laz;
seg[rt].laz = -1;
}
}

//更新
void Update(int Ql, int Qr, int v, int l, int r, int rt) {
if (Ql <= l && Qr >= r) {
seg[rt].val = (r - l + 1) * v;
seg[rt].laz = v;
return ;
}
PushDown(l, r, rt);
int mid = l + (r - l >> 1);
if (Ql <= mid)
Update(Ql, Qr, v, l, mid, lson);
if (Qr > mid)
Update(Ql, Qr, v, mid + 1, r, rson);
PushUp(rt);
}

//查询
int Query(int Ql, int Qr, int l, int r, int rt) {
if (Ql <= l && Qr >= r)
return seg[rt].val;
PushDown(l, r, rt);
int ans = 0;
int mid = l + (r - l >> 1);
if (Ql <= mid)
ans += Query(Ql, Qr, l, mid, lson);
if (Qr > mid)
ans += Query(Ql, Qr, mid + 1, r, rson);
return ans;
}

//二分
int bin_Search(int ll, int rr, int x) {
int l = ll, r = rr;
while (l <= r) {
int mid = l + (r - l >> 1);
if (mid - ll + 1 - Query(ll, mid, 1, rr, 1) >= x)
r = mid - 1;
else l = mid + 1;
}
return l;
}

int main() {
int t, n, m;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
Create(1, n, 1);
while (m--) {
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if (op != 2) {
int cnt = n - l - Query(l + 1, n, 1, n, 1);
if (!cnt)
printf("Can not put any one.\n");
else {
int ll = bin_Search(l + 1, n, 1);
int rr = bin_Search(l + 1, n, min(cnt, r));
Update(ll, rr, 1, 1, n, 1);
printf("%d %d\n", ll - 1, rr - 1);
}
}
else {
printf("%d\n", Query(l + 1, r + 1, 1, n, 1));
Update(l + 1, r + 1, 0, 1, n, 1);
}
}
printf("\n");
}
return 0;
}


05-30 102

09-27 125

10-23 906

05-23 767

10-21 747

11-13 106

05-07 71

07-25 465

08-10 1591

07-26 1778

08-25 1044

01-19 104

05-30 260

08-26 857

05-07 18

07-25 28

02-12 96

#### C/C++学习指南全套教程

09-11
©️2020 CSDN 皮肤主题: 代码科技 设计师: Amelia_0503

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。