Problem Description
There's a queue obeying the first in first out rule. Each time you can either push a number into the queue (+i), or pop a number out from the queue (-i). After a series of operation, you get a sequence (e.g. +1 -1 +2 +4 -2 -4). We call this sequence a queue sequence.

Now you are given a queue sequence and asked to perform several operations:

1. insert p
First you should find the smallest positive number (e.g. i) that does not appear in the current queue sequence, then you are asked to insert the +i at position p (position starts from 0). For -i, insert it into the right most position that result in a valid queue sequence (i.e. when encountered with element -x, the front of the queue should be exactly x).
For example, (+1 -1 +3 +4 -3 -4) would become (+1 +2 -1 +3 +4 -2 -3 -4) after operation 'insert 1'.
2. remove i
Remove +i and -i from the sequence.
For example, (+1 +2 -1 +3 +4 -2 -3 -4) would become (+1 +2 -1 +4 -2 -4) after operation 'remove 3'.
3. query i
Output the sum of elements between +i and -i. For example, the result of query 1, query 2, query 4 in sequence (+1 +2 -1 +4 -2 -4) is 2, 3(obtained by -1 + 4), -2 correspond.

 
Input
There are less than 25 test cases. Each case begins with a number indicating the number of operations n (1 ≤ n ≤ 100000). The following n lines with be 'insert p', 'remove i' or 'query i'(0 ≤ p ≤ length (current sequence), 1 ≤ i, i is granted to be in the sequence).
In each case, the sequence is empty initially.
The input is terminated by EOF.
 
Output
Before each case, print a line "Case #d:" indicating the id of the test case.
After each operation, output the sum of elements between +i and -i.
 
题目大意:这题太难描述了不讲了,亏出题人能想出这么难讲的题……
思路:对于插入最小正数,有一个优先队列维护即可(咋这么多人喜欢用线段树……)
然后序列用一个平衡树维护,我选择了treap,每个结点的右儿子在序列的左边,右结点在序列的右边。
每个点存他的值(val)、这颗子树的负数的总数(neg)、这颗子树的结点的总数(size)、这颗子树的权和(sum)。
可以发现正数和负数的排列是一样的(FIFO),那么插入的正数前面有多少个正数,那么插入的负数前面就有多少个负数,把这个多少个正数算出来,然后插负数的时候尽量往右插即可。
删除操作,在插入的时候记录正数和负数在那个结点上,删除的时候直接旋转到底删掉。
查询操作,因为我们把结点位置记录起来了,那么对于区间[a,b],在a所在的结点往上走,可以算出[a, ~)的权和,同理可以算出(~, b]的权和,然后这两个的和减去所有的数的和(容斥原理)就是这个查询的答案(由于总和一定是0,所以不用减了)。
 
代码(796MS):
 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long LL; const int MAXN = * ;
const int n = ;
int weight[MAXN], child[MAXN][], size[MAXN], neg[MAXN], val[MAXN], pre[MAXN];
LL sum[MAXN];
int pos[MAXN];
int stk[MAXN], top, node_cnt; int m, p, x, root;
char s[]; priority_queue<int> Q;
int int_cnt; void test(int x) {
if(child[x][]) test(child[x][]);
cout<<val[x]<<" "<<sum[x]<<" "<<x<<" "<<pre[x]<<" "<<(child[pre[x]][] == x)<<endl;
//cout<<val[x]<<endl;
if(child[x][]) test(child[x][]);
} void init() {
while(!Q.empty()) Q.pop();
int_cnt = top = node_cnt = ;
} int new_int() {
if(!Q.empty()) {
int ret = -Q.top(); Q.pop();
return ret;
}
return ++int_cnt;
} int new_node(int f, int v) {
int x = (top ? stk[top--] : ++node_cnt);
pre[x] = f;
sum[x] = val[x] = v;
if(v < ) pos[n - v] = x;
else pos[v] = x;
size[x] = ; neg[x] = (v < );
weight[x] = rand();
child[x][] = child[x][] = ;
return x;
} void update(int x) {
sum[x] = sum[child[x][]] + sum[child[x][]] + val[x];
size[x] = size[child[x][]] + size[child[x][]] + ;
neg[x] = neg[child[x][]] + neg[child[x][]] + (val[x] < );
} void rotate(int &x, int t) {
int y = child[x][t];
child[x][t] = child[y][t ^ ];
child[y][t ^ ] = x;
pre[y] = pre[x]; pre[x] = y;
pre[child[x][t]] = x;
update(x); update(y);
x = y;
} void insert1(int f, int &x, int k, int v) {
if(x == ) x = new_node(f, v);
else {
int t = (size[child[x][]] + <= k);
insert1(x, child[x][t], k - t * (size[child[x][]] + ), v);
if(weight[child[x][t]] < weight[x]) rotate(x, t);
}
update(x);
} int cnt_pos(int x, int t) {
if(!x) return ;
int ret = cnt_pos(pre[x], child[pre[x]][] == x);
if(t == ) ret += size[child[x][]] - neg[child[x][]] + (val[x] > );
return ret;
} void insert2(int f, int &x, int k, int v) {
if(x == ) x = new_node(f, v);
else {
int t = (neg[child[x][]] + (val[x] < ) <= k);
insert2(x, child[x][t], k - t * (neg[child[x][]] + (val[x] < )), v);
if(weight[child[x][t]] < weight[x]) rotate(x, t);
}
update(x);
} void remove(int &x) {
if(child[x][] && child[x][]) {
int t = weight[child[x][]] < weight[child[x][]];
rotate(x, t);
remove(child[x][t ^ ]);
} else {
stk[++top] = x;
pre[child[x][]] = pre[child[x][]] = pre[x];
x = child[x][] + child[x][];
}
if(x > ) update(x);
} LL query1(int x, int t) {
if(!x) return ;
LL ret = query1(pre[x], child[pre[x]][] == x);
if(t == ) ret += sum[child[x][]] + val[x];
return ret;
} LL query2(int x, int t) {
if(!x) return ;
LL ret = query2(pre[x], child[pre[x]][] == x);
if(t == ) ret += sum[child[x][]] + val[x];
return ret;
} LL query(int x, int a, int b) {
LL ret = query1(pre[a], child[pre[a]][] == a) + sum[child[a][]];
ret += query2(pre[b], child[pre[b]][] == b) + sum[child[b][]];
return ret;
} void update_parent(int t) {
while(t) update(t), t = pre[t];
} int main() {
for(int t = ; ; ++t) {
if(scanf("%d", &m) == EOF) break;
init();
printf("Case #%d:\n", t);
root = ;
while(m--) {
scanf("%s%d", s, &x);
if(*s == 'i') {
int tmp = new_int();
insert1(, root, x, tmp);
int k = cnt_pos(pos[tmp], ) - ;
insert2(, root, k, -tmp);
}
if(*s == 'r') {
if(root == pos[x]) {
remove(root);
}
else {
int t = pos[x], p = pre[t];
remove(child[p][child[p][] == t]);
update_parent(p);
}
int y = x + n;
if(root == pos[y]) {
remove(root);
}
else {
int t = pos[y], p = pre[t];
remove(child[p][child[p][] == t]);
update_parent(p);
}
Q.push(-x);
}
if(*s == 'q') {
printf("%I64d\n", query(root, pos[x], pos[x + n]));
}
//test(root);
}
}
}

HDU 4441 Queue Sequence(优先队列+Treap树)(2012 Asia Tianjin Regional Contest)的更多相关文章

  1. HDU 4433 locker(DP)(2012 Asia Tianjin Regional Contest)

    Problem Description A password locker with N digits, each digit can be rotated to 0-9 circularly.You ...

  2. HDU-4432-Sum of divisors ( 2012 Asia Tianjin Regional Contest )

    Sum of divisors Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  3. HDU 4436 str2int(后缀自动机)(2012 Asia Tianjin Regional Contest)

    Problem Description In this problem, you are given several strings that contain only digits from '0' ...

  4. HDU 4433 locker 2012 Asia Tianjin Regional Contest 减少国家DP

    意甲冠军:给定的长度可达1000数的顺序,图像password像锁.可以上下滑动,同时会0-9周期. 每个操作.最多三个数字连续操作.现在给出的起始序列和靶序列,获得操作的最小数量,从起始序列与靶序列 ...

  5. HDU 4431 Mahjong(枚举+模拟)(2012 Asia Tianjin Regional Contest)

    Problem Description Japanese Mahjong is a four-player game. The game needs four people to sit around ...

  6. HDU 3726 Graph and Queries(平衡二叉树)(2010 Asia Tianjin Regional Contest)

    Description You are given an undirected graph with N vertexes and M edges. Every vertex in this grap ...

  7. HDU 4441 Queue Sequence

    http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:对于一个序列,每次有三种操作   insert pos  表示在pos插入一个数,这个数是最小的正数 ...

  8. HDU 4441 Queue Sequence(splay)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...

  9. HDU 4468 Spy(KMP+贪心)(2012 Asia Chengdu Regional Contest)

    Description “Be subtle! Be subtle! And use your spies for every kind of business. ”― Sun Tzu“A spy w ...

随机推荐

  1. Python 学习笔记(八)Python列表(三)

    序列 序列:数学上,序列是被排成一列的对象(或事件):这样,每个元素不是在器他元素之前,就是在其他元素之后.这里元素之间的顺序非常重要.<维基百科> 序列是Python中最基本的数据结构. ...

  2. oracle中特殊字符替换

    replace语法: REPLACE(char,search_string,[replacement_string]) 在replace中,每个search_String 都会被replacement ...

  3. js对URL的相关操作集锦

    1.location.href..... (1)self.loction.href="/url" window.location.href="/url"    ...

  4. foreach, for in, for of 之间的异同

    forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数. 注意: forEach() 对于空数组是不会执行回调函数的. 示例代码: var arr = [4, 9, 16, 25]; ...

  5. 最大的最大公约数( 51nod-1179)

    妈耶有日期显示啊,我还写什么... 给出N个正整数,找出N个数两两之间最大公约数的最大值. 例如:N = 4,4个数为:9 15 25 16,两两之间最大公约数的最大值是15同25的最大公约数5.   ...

  6. GUI小程序---理解GUI

    package com.gui; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent ...

  7. jenkins+maven+docker集成java发布(一)自动发布

    JAVA项目持续集成发布 标签(空格分隔): java jenkins 微服务中持续集成自动发布是很重要的一个环节,将不同的模块应用自动部署到一台或者N台服务器中如果采用人工部署的方式不太现实 git ...

  8. Centos安装docker#避免很多坑

    采用yum方式安装 安装: step 1: 安装必要的一些系统工具 yum install -y yum-utils device-mapper-persistent-data lvm2 Step 2 ...

  9. python七类之字符串

    字符串 一.关键字:str 字符串是不可变的可迭代的数据类型 二.方法: name = 'alex uwu sir' .title #标题 使首字母大写​​ 只要有特殊字符隔开,才能分别认为是多个单词 ...

  10. ubuntu64位运行32位程序

    sudo dpkg --add-architecture i386 sudo apt install libc6:i386 转:https://blog.csdn.net/zoomdy/article ...