这里写代码片
题意:有n个花瓶编号从0到n-1,初始花瓶都是空的,然后有两个操作,1 a b表示从位置a开始往后面找b(不够b个也可以)个空花瓶插花,输出插花的首位置和末位置,2 a b表示输出区间[a,b]有多少个花,并且把这个区间内所有花都拿走。
题解:很容易想到用线段树维护区间内有多少个空花瓶,然后操作2可以直接用普通的区间查询和区间修改,操作1可以看作先查询前a-1个花瓶有num个是空的,然后查询第num+1和第num+b个空花瓶的位置,这个查询也可以用线段树查询或二分查找来写。
#include
#include
#include
using namespace std;
const int N = 50005;
int n, q, tree[N << 2], flag[N << 2];
void pushup(int k) {
tree[k] = tree[k * 2] + tree[k * 2 + 1];
}
void pushdown(int k, int left, int right) {
if (flag[k] == 1) {
flag[k * 2] = flag[k * 2 + 1] = flag[k];
tree[k * 2] = tree[k * 2 + 1] = 0;
flag[k] = 0;
}
else if (flag[k] == 2) {
int mid = (left + right) / 2;
flag[k * 2] = flag[k * 2 + 1] = flag[k];
tree[k * 2] = mid - left + 1;
tree[k * 2 + 1] = right - mid;
flag[k] = 0;
}
}
void build(int k, int left, int right) {
flag[k] = 0;
tree[k] = right - left + 1;
if (left != right) {
int mid = (left + right) / 2;
build(k * 2, left, mid);
build(k * 2 + 1, mid + 1, right);
}
}
void modify(int k, int left, int right, int l, int r, int x) {
if (l <= left && right <= r) {
flag[k] = x;
if (x == 1) tree[k] = 0;
else tree[k] = right - left + 1;
return;
}
pushdown(k, left, right);
int mid = (left + right) / 2;
if (l <= mid)
modify(k * 2, left, mid, l, r, x);
if (r > mid)
modify(k * 2 + 1, mid + 1, right, l, r, x);
pushup(k);
}
int query(int k, int left, int right, int l, int r) {
if (l <= left && right <= r)
return tree[k];
pushdown(k, left, right);
int mid = (left + right) / 2, res = 0;
if (l <= mid)
res += query(k * 2, left, mid, l, r);
if (r > mid)
res += query(k * 2 + 1, mid + 1, right, l, r);
pushup(k);
return res;
}
int Find(int k, int left, int right, int l, int r, int pos) {
if (left == right)
return left;
pushdown(k, left, right);
int mid = (left + right) / 2, temp;
if (r <= mid)
temp = Find(k * 2, left, mid, l, r, pos);
else if (l > mid)
temp = Find(k * 2 + 1, mid + 1, right, l, r, pos);
else {
if (pos <= tree[k * 2])
temp = Find(k * 2, left, mid, l, r, pos);
else
temp = Find(k * 2 + 1, mid + 1, right, l, r, pos - tree[k * 2]);
}
pushup(k);
return temp;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &q);
build(1, 0, n - 1);
int op, l, x;
while (q--) {
scanf("%d%d%d", &op, &l, &x);
if (op == 1) {
int temp = query(1, 0, n - 1, l, n - 1);
if (!temp) {
printf("Can not put any one.\n");
continue;
}
else if (temp <= x)
x = temp;
int num = 0;
if (l >= 1)
num = query(1, 0, n - 1, 0, l - 1);
int st = Find(1, 0, n - 1, 0, n - 1, num + 1);
int en = Find(1, 0, n - 1, 0, n - 1, num + x);
printf("%d %d\n", st, en);
modify(1, 0, n - 1, st, en, 1);
} else {
printf("%d\n", x - l + 1 - query(1, 0, n - 1, l, x));
modify(1, 0, n - 1, l, x, 2);
}
}
printf("\n");
}
return 0;
}