Bzoj3545:[ONTAK2010]Peaks:Splay启发式合并

来源:互联网 发布:英国留学手续 知乎 编辑:程序博客网 时间:2024/04/29 17:43

题目链接:[ONTAK2010]Peaks

离线,将边按照边权从小到大排序,询问按照x从小到大排序

对于每个询问,将边权小于他的x的边加入图中,用splay维护每个联通块的权值,查找第k大即可

加入一条边时会合并联通块,这个用Splay的启发式合并

#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;const int maxn=500010;int n,m,f[maxn],Q,qu[maxn],ans[maxn];struct edge{int a,b,w;}e[maxn];struct ques{int v,x,k,id;}q[maxn];struct Nodes{int c[2],fa,v,s;};struct Splay_tree{Nodes t[maxn];void init(){for (int i=1;i<=n;++i) scanf("%d",&t[i].v),t[i].s=1,f[i]=i;}void push_up(int x){if (!x) return;t[x].s=t[t[x].c[0]].s+t[t[x].c[1]].s+1;}void rotate(int p,int x){int mark= p==t[x].c[1];int y=t[p].c[mark^1],z=t[x].fa;if (t[z].c[0]==x) t[z].c[0]=p;if (t[z].c[1]==x) t[z].c[1]=p;if (y) t[y].fa=x; t[x].c[mark]=y;t[p].fa=z; t[p].c[mark^1]=x; t[x].fa=p;push_up(x);}void splay(int p,int k){while (t[p].fa!=k){int x=t[p].fa,y=t[x].fa;if (y==k) rotate(p,x);else if (p==t[x].c[0]^x==t[y].c[0]) rotate(p,x),rotate(p,y);else rotate(x,y),rotate(p,x);}push_up(p);}void ins(int &x,int anc,int now){if (!x){x=now; t[x].fa=anc;t[x].s=1; splay(x,0);return;}if (t[now].v<=t[x].v) ins(t[x].c[0],x,now);else ins(t[x].c[1],x,now);push_up(x);}void merge(int x,int y){splay(x,0); splay(y,0);if (t[x].s>t[y].s) swap(x,y);int head=0,tail=1; qu[0]=y; qu[1]=x;while (head<tail){int u=qu[++head];if (t[u].c[0]) qu[++tail]=t[u].c[0];if (t[u].c[1]) qu[++tail]=t[u].c[1];t[u].c[0]=t[u].c[1]=0;ins(qu[head-1],0,u);}}int qkth(int x,int k){if (t[x].s<k) return -1;if (t[t[x].c[1]].s>=k) return qkth(t[x].c[1],k);else if (t[t[x].c[1]].s+1==k) return t[x].v;else return qkth(t[x].c[0],k-t[t[x].c[1]].s-1);}void debug(int x){if (t[x].c[0]) debug(t[x].c[0]);printf("%d ",t[x].v);if (t[x].c[1]) debug(t[x].c[1]);}}s;bool cmp(const edge &a,const edge &b){return a.w<b.w;}bool cmp2(const ques &a,const ques &b){return a.x<b.x;}int find(int x){return x==f[x]?x:f[x]=find(f[x]);}int main(){scanf("%d%d%d",&n,&m,&Q);s.init();for (int i=1;i<=m;++i)scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].w);sort(e+1,e+m+1,cmp);for (int i=1;i<=Q;++i)scanf("%d%d%d",&q[i].v,&q[i].x,&q[i].k),q[i].id=i;sort(q+1,q+Q+1,cmp2);int pos=1;for (int i=1;i<=Q;++i){while (pos<=m&&e[pos].w<=q[i].x){int a=find(e[pos].a),b=find(e[pos].b);if (a!=b)s.merge(e[pos].a,e[pos].b),f[a]=b;pos++;}int rt=find(q[i].v);s.splay(rt,0);ans[q[i].id]=s.qkth(rt,q[i].k);}for (int i=1;i<=Q;++i) printf("%d\n",ans[i]);}


2 0