题面
Bzoj2733
解析
同样是一道上课时讲的题, 对于每个连通块都维护一个Splay, 连接不同块的操作就等价于合并两棵Splay, 考虑暴力合并, 将较小的Splay断开,依次将每个点插入另外一棵Splay中, 复杂度的话,就照搬wys的PPT了:
查找点所在平衡树的根就暴力查找,一直跳父亲,均摊(应该是吧)跳log次找到根
然后就变成了一道查询第k小的普通平衡树了
第一道一次AC的Splay的题,终于没有写成Spaly了, 不容易啊, 感动
代码:
#includeusing namespace std; const int maxn = 100005; template<class T> void read(T &re) { re=0; T sign=1; char tmp; while((tmp=getchar())&&(tmp<'0'||tmp>'9')) if(tmp=='-') sign=-1; re=tmp-'0'; while((tmp=getchar())&&(tmp>='0'&&tmp<='9')) re=(re<<3)+(re<<1)+(tmp-'0'); re*=sign; } int n, m, q, root[maxn], a[maxn], tot; struct splay_tree{ int s[2], val, fa, siz; }tr[maxn]; int Find(int x) { while(tr[x].fa != 0) x = tr[x].fa; root[x] = x; return x; } void update(int x) { int ls = tr[x].s[0], rs = tr[x].s[1]; tr[x].siz = tr[ls].siz + tr[rs].siz + 1; } void Rotate(int x) { int y = tr[x].fa, z = tr[y].fa, k = (tr[y].s[1] == x), w = (tr[z].s[1] == y), son = tr[x].s[k^1]; tr[y].s[k] = son;tr[son].fa = y; tr[x].s[k^1] = y;tr[y].fa = x; tr[z].s[w] = x;tr[x].fa = z; update(y);update(x); } void Splay(int x, int to, int id) { int y, z; while(tr[x].fa != to) { y = tr[x].fa;z = tr[y].fa; if(z != to) Rotate((tr[y].s[0] == x) ^ (tr[z].s[0] == y)? x: y); Rotate(x); } if(!to) root[id] = x; } void Insert(int x, int y) { int now = root[x], ff = 0; while(now) { tr[now].siz ++; ff = now; if(tr[y].val< tr[now].val) now = tr[now].s[0]; else now = tr[now].s[1]; } tr[ff].s[tr[y].val > tr[ff].val] = y; tr[y].s[0] = tr[y].s[1] = 0; tr[y].fa = ff; Splay(y, 0, x); } void Del(int x, int y) { if(tr[y].s[0]) Del(x, tr[y].s[0]); if(tr[y].s[1]) Del(x, tr[y].s[1]); Insert(x, y); } int kth(int now, int x) { while(1) { int ls = tr[now].s[0], rs = tr[now].s[1]; if(x == tr[ls].siz + 1) return now; if(x <= tr[ls].siz) now = ls; else x -= tr[ls].siz + 1, now = rs; } } int main() { read(n);read(m); for(int i = 1; i <= n; ++i) { root[i] = ++tot; read(tr[root[i]].val); a[tr[root[i]].val] = i; tr[root[i]].siz = 1; } for(int i = 1; i <= m; ++i) { int x, y; read(x);read(y); int p = Find(x), q = Find(y); if(p != q) { if(tr[p].siz < tr[q].siz) swap(p, q); tr[0].s[1] = p; Del(p, q); } } read(q); for(int i = 1; i <= q; ++i) { char opt[5]; int x, y; scanf("%s", opt); read(x);read(y); if(opt[0] == 'Q') { int p = Find(x); if(tr[p].siz < y) printf("-1\n"); else { int id = kth(p, y); printf("%d\n", a[tr[id].val]); Splay(id, 0, p); } } else { int p = Find(x), q = Find(y); if(p != q) { if(tr[p].siz < tr[q].siz) swap(p, q); tr[0].s[1] = p; Del(p, q); } } } return 0; }