裸的线段树,查找的时候可以直接通过节点上面的信息找到第一个和最后一个空瓶子.
#include
using namespace std;
#define maxn 51111
#define pl c<<1
#define pr (c<<1)|1
#define lson tree[c].l,tree[c].mid,c<<1
#define rson tree[c].mid+1,tree[c].r,(c<<1)|1
#define Clear clear
#define find Find
struct node {
int l, r, mid;
int sum;
bool full;//全满标记
bool em; //全空标记
}tree[maxn<<4];
int n, m;
void build_tree (int l, int r, int c) {
tree[c].l = l, tree[c].r = r, tree[c].mid = (l+r)>>1, tree[c].sum = 0;
tree[c].em = 1, tree[c].full = 0;
if (l == r)
return ;
build_tree (lson);
build_tree (rson);
return ;
}
void push_down (int c) {
if (tree[c].l == tree[c].r)
return ;
if (tree[c].em) {
tree[pl].sum = tree[pl].full = 0;
tree[pl].em = 1;
tree[pr].sum = tree[pr].full = 0;
tree[pr].em = 1;
}
else if (tree[c].full) {
tree[pl].sum = (tree[pl].r-tree[pl].l+1);
tree[pr].sum = (tree[pr].r-tree[pr].l+1);
tree[pl].full = tree[pr].full = 1;
tree[pl].em = tree[pr].em = 0;
}
tree[c].em = tree[c].full = 0;
return ;
}
void push_up (int c) {
if (tree[c].l == tree[c].r)
return ;
tree[c].sum = tree[pl].sum + tree[pr].sum;
tree[c].full = tree[pl].full&tree[pr].full;
tree[c].em = tree[pl].em&tree[pr].em;
return ;
}
int sum (int l, int r, int c, int x, int y) {
if (y < x)
return 0;
push_down (c);
int ans = 0;
if (l == x && r == y) {
return tree[c].sum;
}
else if (tree[c].mid >= y) {
return sum (lson, x, y);
}
else if (tree[c].mid < x) {
return sum (rson, x, y);
}
else {
return sum (lson, x, tree[c].mid) + sum (rson, tree[c].mid+1, y);
}
}
void clear (int l, int r, int c, int x, int y) { //清空花瓶
if (y < x)
return ;
push_down (c);
if (x == l && y == r) {
tree[c].em = 1;
tree[c].full = 0;
tree[c].sum = 0;
return ;
}
else if (tree[c].mid >= y) {
clear (lson, x, y);
}
else if (tree[c].mid < x) {
clear (rson, x, y);
}
else {
clear (lson, x, tree[c].mid);
clear (rson, tree[c].mid+1, y);
}
push_up (c);
}
int find (int l, int r, int c, int x) {
push_down (c);
if (l == r)
return l;
int all = tree[pl].r-tree[pl].l+1-tree[pl].sum; //左儿子的空瓶子
if (all >= x) {
return find (lson, x);
}
else
return find (rson, x-all);
}
void add (int l, int r, int c, int x, int y) {
push_down (c);
if (l == x && r == y) {
tree[c].sum = r-l+1;
tree[c].full = 1;
tree[c].em = 0;
return ;
}
else if (tree[c].mid >= y) {
add (lson, x, y);
}
else if (tree[c].mid < x) {
add (rson, x, y);
}
else {
add (lson, x, tree[c].mid);
add (rson, tree[c].mid+1, y);
}
push_up (c);
}
void solve (int x, int y) {
int ans = sum (0, n-1, 1, x, n-1);
if (n-x-ans == 0) {
printf ("Can not put any one.\n");
return ;
}
int l = 0, r = 0;
int pre = n-x-ans;
ans = sum (1, n, 1, 0, x-1); ans = x-ans; //x之前有ans个空花瓶
l = find (0, n-1, 1, ans+1); //找到第ans+1个空花瓶的位置
if (!r) r = find (0, n-1, 1, min (ans+y, ans+pre)); //找到第ans+y个空花瓶的位置
printf ("%d %d\n", l, r);
add (0, n-1, 1, l, r);
}
void debug (int c) {
cout << "l:" << tree[c].l << " r:" << tree[c].r << " sum:" << tree[c].sum << endl;
if (tree[c].l == tree[c].r)
return ;
debug (pl);
debug (pr);
return ;
}
int main () {
//freopen ("in", "r", stdin);
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%d%d", &n, &m);
build_tree (0, n-1, 1);
for (int i = 1; i <= m; i++) {
int op;
scanf ("%d", &op);
if (op == 1) {
int x, y;
scanf ("%d%d", &x, &y);
solve (x, y);
}
else if (op == 2) {
int x, y;
scanf ("%d%d", &x, &y);
printf ("%d\n", sum (0, n-1, 1, x, y));
clear (0, n-1, 1, x, y);
}
}
printf ("\n");
}
return 0;
}