坑爹splay
很裸就是了
记录每个数正数和负数的节点编号
insert p,先插正数,设正数前面有x个正数,然后插到第x+1个负数前面。注意有边界问题,机智的我加了个+0和-0
query p,直接split查
remove p,直接提前驱后继然后删
另外要用一个可以动态维护最小值的东西来维护insert的数。
怕被卡常,手写了个线段树。其实平板电视也不是不可以?
有些要注意的地方。。。
比如remove完一个节点之后要upd
求第k个负数的姿势有一点点不同
+0和-0处理起来有些地方也要注意一下
hdu是I64而不是ll(不过好像用ll的时候就A掉了?)
总共写了1h+调了0.5h的样子。
还好吧。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a,_=b;i<=_;i++)
#define per(i,a,b) for(int i=a,_=b;i>=_;i--)
#define maxn 200007
inline int rd() {
char c = getchar() ;
while (!isdigit(c) && c != '-') c = getchar();
int x = 0 , f = 1;
if (c == '-') f = -1 ; else x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x * f;
}
typedef long long ll;
typedef int arr_int[maxn];
typedef ll arr_ll [maxn];
arr_int sz , cnt , fa , neg , pos , val;
arr_ll sum;
int ch[maxn][2] , rt , n , tot;
struct SegTree {
int cnt[maxn * 4 + 1] , p , tg[maxn * 4 + 1];
#define lc (u << 1)
#define rc (u << 1 | 1)
#define T int u = 1 , int l = 1 , int r = n
#define L lc , l , m
#define R rc , m + 1 , r
void modi(T) {
if (l == r) {
cnt[u] = 0;
return ;
}
if (tg[u]) {
cnt[lc] = cnt[rc] = 0;
tg[lc] = tg[rc] = 1;
tg[u] = 0;
}
int m = (l + r) >> 1;
if (p <= m) modi(L);
else modi(R);
cnt[u] --;
}
int que(T) {
if (l == r) return cnt[u] = 1 , l;
if (tg[u]) {
cnt[lc] = cnt[rc] = 0;
tg[lc] = tg[rc] = 1;
tg[u] = 0;
}
int m = (l + r) >> 1 , x;
if (cnt[lc] < m - l + 1) x = que(L);
else x = que(R);
cnt[u] ++;
return x;
}
inline void add(int x) {
p = x;
modi();
}
inline int get() {
return que();
}
inline void clear() {
tg[1] = 1 , cnt[1] = 0;
}
#undef lc
#undef rc
#undef T
#undef L
#undef R
}_num;
#define lc ch[u][0]
#define rc ch[u][1]
#define KEY ch[ch[rt][1]][0]
void dbg(int u) {
if (lc) dbg(lc);
printf("%d " , val[u]);
if (rc) dbg(rc);
}
inline int newnode(int v , int f) {
++ tot;
if (f > 0) pos[v] = tot;
else neg[v] = tot;
val[tot] = v * f;
sum[tot] = val[tot];
cnt[tot] = (f < 0);
sz [tot] = 1;
return tot;
}
inline void delnode(int u) {
int f = fa[u];
ch[f][ch[f][1] == u] = 0;
fa[u] = 0;
}
inline void upd(int u) {
sum[u] = val[u];
cnt[u] = (val[u] <= 0 && u != 1);
sz[u] = 1;
if (lc) sum[u] += sum[lc] , cnt[u] += cnt[lc] , sz[u] += sz[lc];
if (rc) sum[u] += sum[rc] , cnt[u] += cnt[rc] , sz[u] += sz[rc];
}
inline void mt() { upd(ch[rt][1]) , upd(rt) ; }
void input() {
_num.clear();
rep (i , 1 , tot) fa[i] = 0 , ch[i][0] = ch[i][1] = 0;
tot = 0;
rt = newnode(0 , 1);
pos[0] = tot;
ch[rt][1] = newnode(0 , -1);
neg[0] = tot , fa[tot] = rt;
upd(rt);
}
inline void rot(int u , int&aim) {
int f = fa[u] , g = fa[f];
int l = (ch[f][1] == u) , r = l ^ 1;
if (f != aim) ch[g][ch[g][1] == f] = u;
else aim = u;
if (ch[u][r]) fa[ch[u][r]] = f;
fa[f] = u , fa[u] = g;
ch[f][l] = ch[u][r] , ch[u][r] = f;
upd(f) , upd(u);
}
inline void splay(int u , int&aim) {
for (;u != aim;rot(u , aim)) {
int f = fa[u] , g = fa[f];
if (f != aim) rot(((ch[f][0] == u) ^ (ch[g][0] == f)) ? u : f , aim);
}
upd(u);
}
inline int kth(int k) {
int u = rt;
while (sz[lc] + 1 != k) {
if (sz[lc] + 1 < k)
k -= sz[lc] + 1 , u = rc;
else
u = lc;
}
return u;
}
inline int kth_neg(int k) {
int u = rt;
for (;;) {
if (val[u] < 0 || u == 2) {
if (cnt[lc] + 1 == k) break;
if (cnt[lc] + 1 > k)
u = lc;
else
k -= cnt[lc] + 1 , u = rc;
} else {
if (cnt[lc] >= k)
u = lc;
else
k -= cnt[lc] , u = rc;
}
}
return u;
}
inline int find_pre(int u) {
splay(u , rt);
for (u = lc;rc;u = rc);
return u;
}
inline int find_nxt(int u) {
splay(u , rt);
for (u = rc;lc;u = lc);
return u;
}
inline void split(int u , int v) {
splay(u , rt);
splay(v , ch[u][1]);
}
inline void insert(int p) {
int x = _num.get();
split(kth(p + 1) , kth(p + 2));
KEY = newnode(x , 1);
fa[KEY] = ch[rt][1] , mt();
splay(pos[x] , rt);
int t = kth_neg(sz[ch[rt][0]] - cnt[ch[rt][0]]);
split(find_pre(t) , t);
KEY = newnode(x , -1);
fa[KEY] = ch[rt][1] , mt();
splay(neg[x] , rt);
}
inline void query(int x) {
split(pos[x] , neg[x]);
printf("%lld\n" , sum[KEY]);
}
inline void remove(int x) {
split(find_pre(pos[x]) , find_nxt(pos[x]));
delnode(KEY) , mt();
split(find_pre(neg[x]) , find_nxt(neg[x]));
delnode(KEY) , mt();
_num.add(x);
pos[x] = neg[x] = 0;
}
void solve() {
char cmd[20];
int p;
rep (i , 1 , n) {
scanf("%s%d" , cmd , &p);
if (cmd[0] == 'i') {
insert(p);
} else if (cmd[0] == 'q') {
query(p);
} else if (cmd[0] == 'r') {
remove(p);
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
freopen("data.out" , "w" , stdout);
#endif
int T = 1;
while (scanf("%d" , &n) == 1) {
printf("Case #%d:\n" , T ++);
input();
solve();
}
return 0;
}