HDU_1512
这个题目用左偏树做的居多,昨天晚上突然想到其实用一棵splay也能方便的实现合并的操作,于是就用splay写了。
在fight之前,要先找到两棵树中的最大值,然后splay到根部并修改。之后为了实现合并,可以将一棵splay“最右边”的元素splay到根部,这样根的右子树就为空了,直接把另一棵树放到这个位置即可。
#include<stdio.h> #include<string.h> #define MAXD 100010 #define INF 0x7fffffff int N; struct Splay { int pre, ls, rs, key, max; void update(); void zig(int ); void zag(int ); void splay(int ); void renew() { pre = ls = rs = 0; } }sp[MAXD]; int Max(int x, int y) { return x > y ? x : y; } void Splay::update() { max = Max(Max(sp[ls].max, sp[rs].max), key); } void Splay::zig(int x) { int y = rs, fa = pre; rs = sp[y].ls, sp[rs].pre = x; sp[y].ls = x, pre = y; sp[y].pre = fa, sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y; update(); } void Splay::zag(int x) { int y = ls, fa = pre; ls = sp[y].rs, sp[ls].pre = x; sp[y].rs = x, pre = y; sp[y].pre = fa, sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y; update(); } void Splay::splay(int x) { int y, z; for(; pre != 0;) { y = pre; if(sp[y].pre == 0) sp[y].rs == x ? sp[y].zig(y) : sp[y].zag(y); else { z = sp[y].pre; if(sp[z].rs == y) { if(sp[y].rs == x) sp[z].zig(z), sp[y].zig(y); else sp[y].zag(y), sp[z].zig(z); } else { if(sp[y].ls == x) sp[z].zag(z), sp[y].zag(y); else sp[y].zig(y), sp[z].zag(z); } } } update(); } void init() { int i; sp[0].max = -INF; for(i = 1; i <= N; i ++) { sp[i].renew(); scanf("%d", &sp[i].key); sp[i].max = sp[i].key; } } int findmax(int cur, int v) { if(sp[cur].key == v) return cur; if(sp[sp[cur].ls].max == v) return findmax(sp[cur].ls, v); else return findmax(sp[cur].rs, v); } int findlast(int cur) { if(sp[cur].rs) return findlast(sp[cur].rs); else return cur; } int romax(int x) { int t = findmax(x, sp[x].max); sp[t].splay(t); return t; } int rolast(int x) { int t = findlast(x); sp[t].splay(t); return t; } int findroot(int x) { for(; sp[x].pre != 0; x = sp[x].pre); return x; } void fight(int x, int y) { int tx, ty, t; tx = findroot(x), ty = findroot(y); if(tx == ty) printf("-1\n"); else { tx = romax(tx), ty = romax(ty); sp[tx].key /= 2, sp[tx].update(); sp[ty].key /= 2, sp[ty].update(); t = rolast(tx); sp[t].rs = ty, sp[ty].pre = t; sp[t].update(); printf("%d\n", sp[t].max); } } void solve() { int i, x, y, m; scanf("%d", &m); for(i = 0; i < m; i ++) { scanf("%d%d", &x, &y); fight(x, y); } } int main() { while(scanf("%d", &N) == 1) { init(); solve(); } return 0; }