BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay
Description
在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。
Input
第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。
Output
对于每组询问,输出一个整数表示答案。
有小于等于 $x$ 这个条件十分不好办 .
考虑离线,按照 $x$ 从小到大依次加入,查询的时候直接在 $splay$ 中查询第 $k$ 大即可.
#include <cstdio> #include <algorithm> #include <stack> #define N 600005 #define inf 1000000002 #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; int splay_cnt; namespace IO { char *p1,*p2,buf[100000]; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x; } }; struct Edge { int u , v , c ; }ed[N]; bool cmp(Edge a, Edge b) { return a.c < b.c; } struct Ask { int u , x , k , id ; }as[N]; bool cmp2(Ask a, Ask b) { return a.x < b.x; } #define lson ch[x][0] #define rson ch[x][1] stack <int> S; int answer[N], h[N], size[N], f[N], ch[N][2], siz[N], val[N], rt[N], p[N], mk = 0; inline void init(int sz) { for(int i = 1; i <= sz ; ++i) S.push(i); for(int i = 1; i <= sz ; ++i) p[i] = i, size[i] = 1; } int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); } inline int newnode() { int u = S.top(); S.pop(); return u; } inline int get(int x) { return ch[f[x]][1] == x; } inline void pushup(int x) { siz[x] = siz[lson] + siz[rson] + 1; } inline void rotate(int x) { int old = f[x], fold = f[old], which = get(x); ch[old][which] = ch[x][which ^ 1], f[ch[old][which]] = old; ch[x][which ^ 1] = old, f[old] = x, f[x] = fold; if(fold) ch[fold][ch[fold][1] == old] = x; pushup(old), pushup(x); } inline void splay(int x, int &tar) { int u = f[tar]; for(int fa; (fa = f[x]) ^ u; rotate(x)) if(f[fa] ^ u) rotate(get(fa) == get(x) ? fa : x); tar = x; } inline int kth(int x, int k) { if(siz[x] < k) return inf; while(1) { if(k > siz[rson]) { k -= (siz[rson] + 1); if(!k) return x; else x = lson; } else x = rson; } } inline void insert(int &x, int ff, int v) { if(!x) { mk = x = newnode(); f[x] = ff, val[x] = v, pushup(x); return; } insert(ch[x][v > val[x]], x, v), pushup(x); } inline void DFS(int y, int x) { if(lson) DFS(y, lson); if(rson) DFS(y, rson); int v = val[x]; S.push(x), val[x] = siz[x] = lson = rson = f[x] = 0, insert(rt[y], 0, v), ++splay_cnt; if(splay_cnt % 6 == 0) splay(mk, rt[y]); } inline void connect(int o) { int u = ed[o].u, v = ed[o].v; int x = find(u), y = find(v); if(x ^ y) { if(size[y] < size[x]) swap(x, y); p[x] = y, size[y] += size[x], DFS(y, rt[x]); } } int main() { using namespace IO; // setIO("input"); int n, m, q, i, j; n = rd(), m = rd(), q = rd(), init(n); for(i = 1; i <= n ; ++i) h[i] = rd(), insert(rt[i], 0, h[i]); for(i = 1; i <= m ; ++i) ed[i].u = rd(), ed[i].v = rd(), ed[i].c = rd(); sort(ed + 1, ed + 1 + m, cmp); for(i = 1; i <= q ; ++i) { as[i].u = rd(), as[i].x = rd(), as[i].k = rd(), as[i].id = i; } sort(as + 1, as + 1 + q, cmp2); for(i = j = 1; i <= q; ++i) { while(ed[j].c <= as[i].x && j <= m) connect(j), ++j; int l = kth(rt[find(as[i].u)], as[i].k); answer[as[i].id] = (l == inf ? inf : val[l]); if(l ^ inf) { ++splay_cnt; if(splay_cnt % 6 == 0) splay(l, rt[find(as[i].u)]); } } for(i = 1; i <= q; ++i) printf("%d\n",answer[i] == inf ? -1 : answer[i]); return 0; }