·http://acm.hdu.edu.cn/showproblem.php?pid=4441
代码写了两个小时,可是AC却在两天后
最近犯的错误都是肉眼无法辨别啊,下次写这种数据结构题一定仔细再仔细
网上应该已经有人写过题解了,我的做法大体相同,稍有不同
1:找不在集合中的最小的正数只需维护一个set即可。set保存的是所有不在集合中的数。删除一对+i -i 的时候就在set插入一个+i,插入i的时候就在set中删掉
2:怎么插入-i,很显然,找到i后面第一个正数对应的负数即可,-i就插在这个负数的前面,因为最迟不能迟于这个负数出队列
所有的操作对于伸展树来说都是模拟而已,只要敲好那三个函数,调试的时候输出整棵树看一下就一目了然
我依旧水水的~
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <map>
#include <set>
typedef __int64 lld;
const int inf = ~0u >> 2;
using namespace std;
const int maxn = 300010;
//splay tree
#define L ch[x][0]
#define R ch[x][1]
#define KT (ch[ch[rt][1]][0])
struct SplayTree {
int ch[maxn][2];
int pre[maxn], sz[maxn], val[maxn];
int rt, top;
int cnt[maxn];
void Rotate(int x, int f) {
int y = pre[x];
ch[y][!f] = ch[x][f];
pre[ch[x][f]] = y;
pre[x] = pre[y];
if (pre[x])
ch[pre[y]][ch[pre[y]][1] == y] = x;
ch[x][f] = y;
pre[y] = x;
up(y);
}
void Splay(int x, int goal) {
while (pre[x] != goal) {
if (pre[pre[x]] == goal)
Rotate(x, ch[pre[x]][0] == x);
else {
int y = pre[x], z = pre[y];
int f = (ch[z][0] == y);
if (ch[y][f] == x)
Rotate(x, !f), Rotate(x, f);
else
Rotate(y, f), Rotate(x, f);
}
}
up(x);
if (goal == 0)
rt = x;
}
void RTO(int k, int goal) {
int x = rt;
while (sz[L] + 1 != k) {
if (k < sz[L] + 1)
x = L;
else {
k -= (sz[L] + 1);
x = R;
}
}
Splay(x, goal);
}
void up(int x) {
sz[x] = 1 + sz[L] + sz[R];
cnt[x] = cnt[L] + cnt[R] + (val[x] > 0);
sum[x] = val[x] + sum[L] + sum[R];
}
void Newnode(int &x, int c, int f) {
x = ++top;
if (c < 0)
neg[-c] = x;
else
posi[c] = x;
L = R = 0;
sz[x] = 1;
pre[x] = f;
val[x] = sum[x] = c;
cnt[x] = (val[x] > 0);
}
void init(int n) {
mm.clear();
for (int i = 1; i <= n; i++) mm.insert(i);
ch[0][0] = ch[0][1] = pre[0] = 0;
sz[0] = rt = top = 0; cnt[0]=0;
sum[0] = 0;
Newnode(rt, 0, 0);
Newnode(ch[rt][1],0, rt);
up(ch[rt][1]);
up(rt);
}
void vist(int x) {
if(x) {
printf("结点%2d : 左儿子 %2d 右儿子 %2d val: %2d sum=%d\n",x,ch[x][0],ch[x][1],val[x],sum[x]);
vist(L);
vist(R);
}
}
void debug() {
puts("");
vist(rt);
puts("");
}
void Find(int x,int &ans) {
if(!x) return ;
if(cnt[L]) {
Find(L,ans);
} else if(val[x] > 0) {
ans=x;
return ;
} else {
Find(R,ans);
}
}
void Insert(int position) {
int l = position + 1, r = position + 2;
int v = *mm.begin();
mm.erase(mm.begin());
RTO(l, 0);
RTO(r, rt);
Newnode(KT, v, ch[rt][1]);
up(ch[rt][1]);
up(rt);
Splay(posi[v],0);
int node = -1;
if(cnt[ch[rt][1]]) Find(ch[rt][1],node);
if (node == -1) {
RTO(sz[rt] - 1, 0);
RTO(sz[rt], rt);
Newnode(KT, -v, ch[rt][1]);
up(ch[rt][1]);
up(rt);
} else {
int VV = val[node];
Splay(neg[VV], 0);
RTO(sz[ch[rt][0]], 0);
Splay(neg[VV],rt);
Newnode(KT, - v, ch[rt][1]);
up(ch[rt][1]);
up(rt);
}
}
void Query(int num) {
int a=posi[num],b=neg[num];
Splay(a, 0);
Splay(b, rt);
printf("%I64d\n", sum[KT]);
}
void Remove(int num) {
mm.insert(num);
Splay(posi[num], 0);
Del_Root();
Splay(neg[num], 0);
Del_Root();
}
void Del_Root() {
int t = rt;
if (ch[rt][1]) {
rt = ch[rt][1];
RTO(1, 0);
ch[rt][0] = ch[t][0];
if (ch[rt][0])
pre[ch[rt][0]] = rt;
} else
rt = ch[rt][0];
pre[rt] = 0;
up(rt);
}
int posi[maxn]; //某个正数对应的伸展树中的节点
int neg[maxn]; //某个负数对应的伸展树中的节点
lld sum[maxn];
set<int> mm; //保存当前不在集合中的最小的正数
} spt;
int main() {
int n, num,ca=1;
char cmd[20];
while (scanf("%d", &n) != EOF) {
printf("Case #%d:\n",ca++);
spt.init(n);
for (int i = 0; i < n; i++) {
scanf("%s%d", cmd, &num);
if (cmd[0] == 'i') {
spt.Insert(num);
} else if (cmd[0] == 'q') {
spt.Query(num);
} else {
spt.Remove(num);
}
}
}
return 0;
}