bzoj 2733 Splay 启发式合并,名次树
2015-02-05 19:51
302 查看
题意:给定一个带点权的无向图,有两种操作:
1、将两个连通分量合并。
2、查询某个连通分量里的第K大点。
题解:
用并查集维护连通关系,一开始建立n棵splay树,然后不断合并,查询。
处理技巧:
1、每个顶点u所在的Splay就是T[find(u)]。
2、每个顶点在树中对应的节点编号就是该顶点的编号。
View Code
1、将两个连通分量合并。
2、查询某个连通分量里的第K大点。
题解:
用并查集维护连通关系,一开始建立n棵splay树,然后不断合并,查询。
处理技巧:
1、每个顶点u所在的Splay就是T[find(u)]。
2、每个顶点在树中对应的节点编号就是该顶点的编号。
#include <cstdio> #include <iostream> #define maxn 100110 using namespace std; int key[maxn], pre[maxn], son[maxn][2], siz[maxn], ntot; struct Splay { int root; Splay():root(0){} void update( int nd ) { siz[nd] = siz[son[nd][0]] + siz[son[nd][1]] + 1; } void rotate( int nd, int d ) { int p = pre[nd]; int s = son[nd][!d]; int ss = son[s][d]; son[nd][!d] = ss; son[s][d] = nd; if( p ) son[p][ nd==son[p][1] ] = s; else root = s; pre[nd] = s; pre[s] = p; if( ss ) pre[ss] = nd; update( nd ); update( s ); } void splay( int nd, int top=0 ) { while( pre[nd]!=top ) { int p = pre[nd]; int nl = nd==son[p][0]; if( pre[p]==top ) { rotate( p, nl ); } else { int pp = pre[p]; int pl = p==son[pp][0]; if( nl==pl ) { rotate( pp, pl ); rotate( p, nl ); } else { rotate( p, nl ); rotate( pp, pl ); } } } } int initnode( int nd, int k, int p ) { key[nd] = k; pre[nd] = p; son[nd][0] = son[nd][1] = 0; siz[nd] = 1; return nd; } void insert( int k, int nnd ) { if( !root ) { root = initnode(nnd,k,0); return; } int nd = root; while( son[nd][ k>key[nd] ] ) nd = son[nd][ k>key[nd] ]; son[nd][ k>key[nd] ] = initnode(nnd,k,nd); update( nd ); splay( nd ); } int nth( int n ) { int nd = root; while( 1 ) { int ls = siz[son[nd][0]]; if( n<=ls ) { nd = son[nd][0]; } else if( n>=ls+2 ) { nd = son[nd][1]; n -= ls+1; } else { break; } } splay(nd); return nd; } inline int size() { return siz[root]; } static void join( Splay &T , int snd ) { if( !snd ) return; join( T, son[snd][0] ); join( T, son[snd][1] ); T.insert( key[snd], snd ); } }; int n, m, q; int fa[maxn]; Splay T[maxn]; int find( int a ) { return a==fa[a] ? a : fa[a]=find(fa[a]); } void join( int a, int b ) { if( find(a)==find(b) ) return; if( T[find(a)].size() > T[find(b)].size() ) swap(a,b); Splay::join( T[find(b)], T[find(a)].root ); fa[find(a)] = find(b); } int main() { scanf( "%d%d", &n, &m ); for( int i=1,w; i<=n; i++ ) { scanf( "%d", &w ); fa[i] = i; T[i].insert( w, i ); } for( int i=1,u,v; i<=m; i++ ) { scanf( "%d%d", &u, &v ); join(u,v); } scanf( "%d", &q ); while( q-- ) { char ch[2]; int a, b; scanf( "%s%d%d", ch, &a, &b ); if( ch[0]=='B' ) { join(a,b); } else { if( !(1<=b&&b<=T[find(a)].size()) ) printf( "-1\n" ); else printf( "%d\n", T[find(a)].nth(b) ); } } }
View Code
相关文章推荐
- BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]
- bzoj 2733 永无乡 Splay 启发式合并
- 【BZOJ 2733】 [HNOI2012]永无乡|Splay启发式合并
- bzoj 2733(splay启发式合并)
- BZOJ[2733][HNOI2012]永无乡 Splay启发式合并
- 【splay启发式合并】bzoj 2733 永无乡
- bzoj 2733 [HNOI2012]永无乡 splay启发式合并
- 【BZOJ 2733】【HNOI 2012】永无乡 Splay启发式合并
- [BZOJ][平衡树+启发式合并][替罪羊树]2733: [HNOI2012]永无乡
- bzoj 2733 平衡树启发式合并
- BZOJ 2733([HNOI2012]永无乡-Treap启发式合并)
- Bzoj3545:[ONTAK2010]Peaks:Splay启发式合并
- BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)
- 【BZOJ2809】【splay启发式合并】dispatching
- bzoj 2733: [HNOI2012]永无乡(线段树启发式合并)
- BZOJ 2733: [HNOI2012]永无乡 启发式合并treap
- [bzoj 2733]启发式合并权值线段树
- 【BZOJ 2733】[HNOI2012]永无乡 启发式合并treap
- 【BZOJ 2733】【HNOI 2012】永无乡【treap启发式合并】
- 指令总预算BZOJ 2809([Apio2012]dispatching-Splay启发式合并)