题意:现有10^6个位置(cell),每个位置上可以放若干个cube,对于任意的两个数i<=j如果满足[i,j]之间任意位置都有cube且i-1和j+1没有箱子,则称[i,j]为一个Tower。
现有10^6条修改和查询,保证合法性:
- put <x> <c> - put c cubes on cell x
- tput <t> <x> <c> - put c cubes on column x in tower with number t (towers are numbered from left to the right)
- towers - print total number of towers built
- cubes <t> - print the number of cubes in the tower t
- length <t> - print the length of the tower t
- tcubes <t> <x> - print the number of cubes in column x of the tower t
解法:根据题意知,需要维护的统计量有:某个cell的cube数,某个tower的cube数,某个tower的长度,及tower数,第i个tower的左端点。只有第一种会改变tower的分布(产生新tower或合并若干个tower)由于tower的产生具有传递性因此很容易想到并查集维护(父节点相当于所在线段的左端点),Treap保存现有线段的左端点,产生tower时将左端点插入合并tower时将右侧左端点删除,这样便可以维护第i个tower的左端点。
#include<cstdio>
#include<cstdlib>
using namespace std;
#define maxn 1000010
struct TreeNode {
int key;
int left, right;
int size;
int pri;
void init() {
left = right = 0;
size = 1;
pri = rand();
}
};
struct Treap {
TreeNode nodes[maxn];
int root, cnt, count;
int stack[maxn], top;
void init() {
count = root = cnt = top = 0;
nodes[0].pri = -0x7FFFFFFF;
}
int newnode() {
int ret;
if (top)
ret = stack[--top];
else
ret = ++cnt;
nodes[ret].init();
return ret;
}
void push_up(int idx) {
nodes[idx].size = nodes[nodes[idx].left].size
+ nodes[nodes[idx].right].size + 1;
}
void leftRotate(int &root) {
int tmp = nodes[root].right;
nodes[root].right = nodes[nodes[root].right].left;
nodes[tmp].left = root;
push_up(root);
push_up(tmp);
root = tmp;
}
void rightRotate(int &root) {
int tmp = nodes[root].left;
nodes[root].left = nodes[nodes[root].left].right;
nodes[tmp].right = root;
push_up(root);
push_up(tmp);
root = tmp;
}
void insert(int k) {
count++;
insert(k, root);
}
void insert(int k, int& root) {
if (!root) {
root = newnode();
nodes[root].key = k;
return;
} else if (k < nodes[root].key) {
insert(k, nodes[root].left);
if (nodes[nodes[root].left].pri > nodes[root].pri)
rightRotate(root);
} else {
insert(k, nodes[root].right);
if (nodes[nodes[root].right].pri > nodes[root].pri)
leftRotate(root);
}
push_up(root);
}
void del(int k) {
count--;
del(root, k);
}
void del(int &root, int k) {
if (nodes[root].key == k) {
if (!nodes[root].left && !nodes[root].right) {
stack[top++] = root;
root = 0;
return;
}
if (nodes[nodes[root].left].pri > nodes[nodes[root].right].pri) {
rightRotate(root);
del(nodes[root].right, k);
} else {
leftRotate(root);
del(nodes[root].left, k);
}
push_up(root);
return;
}
if (k < nodes[root].key)
del(nodes[root].left, k);
else
del(nodes[root].right, k);
push_up(root);
}
int select(int k) {
return select(root, k);
}
int select(int root, int k) {
int s = nodes[nodes[root].left].size;
if (s >= k)
return select(nodes[root].left, k);
if (s + 1 == k)
return nodes[root].key;
return select(nodes[root].right, k - 1 - s);
}
} tree;
int num[maxn], p[maxn];//每个点的cube数及所在线段的左端点
int count[maxn], len[maxn];//做端点为i的线段的cube数及长度
int n, t, x, c;
void init() {
tree.init();
for (int i = 0; i < maxn; i++) {
len[i] = count[i] = num[i] = 0;
p[i] = i;
}
}
int find(int x) {
if (x == p[x])
return x;
p[x] = find(p[x]);
return p[x];
}
void put() {
scanf("%d%d", &x, &c);
if (num[x] == 0) {
count[x] = num[x] = c;
len[x] = 1;
tree.insert(x);
if (num[x + 1] != 0) {
p[x + 1] = x;
len[x] += len[x + 1];
count[x] += count[x + 1];
tree.del(x + 1);
}
if (num[x - 1] != 0) {
tree.del(x);
int px = find(x - 1);
p[x] = px;
len[px] += len[x];
count[px] += count[x];
}
} else {
int px = find(x);
num[x] += c;
count[px] += c;
}
}
void tput() {
scanf("%d%d%d", &t, &x, &c);
int temp = tree.select(t);
num[temp + x - 1] += c;
count[temp] += c;
}
void towers() {
int temp = tree.count;
printf("%d towers\n", temp);
}
void cubes() {
scanf("%d", &t);
int temp = tree.select(t);
printf("%d cubes in %dth tower\n", count[temp],t);
}
void length() {
scanf("%d", &t);
int temp = tree.select(t);
printf("length of %dth tower is %d\n",t,len[temp]);
}
void tcubes() {
scanf("%d%d",&t,&x);
int temp = tree.select(t);
printf("%d cubes in %dth column of %dth tower\n",num[temp+x-1],x,t);
}
int main() {
char ch[10];
scanf("%d", &n);
init();
while (n--) {
scanf("%s", ch);
if (ch[0] == 'p')
put();
if(ch[0]=='t'&&ch[1]=='p')
tput();
if(ch[0]=='t'&&ch[1]=='o')
towers();
if(ch[0]=='c')
cubes();
if(ch[0]=='l')
length();
if(ch[0]=='t'&&ch[1]=='c')
tcubes();
}
return 0;
}