Bzoj3545 [ONTAK2010]Peaks
Posted SilverNebula
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj3545 [ONTAK2010]Peaks相关的知识,希望对你有一定的参考价值。
Submit: 2038 Solved: 535
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
对于每组询问,输出一个整数表示答案。
Sample Input
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2
Sample Output
1
-1
8
HINT
【数据范围】
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
Source
Kruskal 启发式合并 树 treap 脑洞题
将询问离线,按询问x值从小到大排序,回答每个询问前将x值小于询问值的边加进集合,进行启发式合并。
用treap维护集合内的结点,进行排名查询以回答询问。
算法比较好想,然而并不会写treap的启发式合并……
各种开脑洞,发现要么太难实现,要么实现了不能保证二叉树性质WAWAWA
依稀记得听说过可持久化treap的合并是以某个权值为界把treap拆分开,再合并成一整棵新树,想想就好难写。
最后放弃了挣扎,选择了暴力把一棵treap上的点全建到另一棵treap上。
然而一对拍又挂了,检查了好久好久,发现合并时候少传了一个地址。
于是一下午+半个晚上就水过去了。
随机数种子很好用,并没有特殊的意义(认真脸)
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=120010; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 13 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 14 return x*f; 15 } 16 struct edge{ 17 int x,y,w; 18 bool operator < (edge b)const{return w<b.w;} 19 }e[mxn*5]; 20 struct QUE{ 21 int v,x,k,id; 22 bool operator < (QUE b)const{return x<b.x;} 23 }q[mxn*5]; 24 // 25 int fa[mxn],sz[mxn]; 26 int find(int x){ 27 return fa[x]==x?x:fa[x]=find(fa[x]); 28 } 29 // 30 struct node{ 31 int l,r; 32 int v,sz,cnt; 33 int rand; 34 }t[mxn*5]; 35 int rot[mxn],cnt; 36 void pushup(int x){ 37 t[x].sz=t[t[x].l].sz+t[t[x].r].sz+t[x].cnt; 38 } 39 void Rt(int &k){ 40 int now=t[k].l; 41 t[k].l=t[now].r; 42 t[now].r=k; 43 pushup(k);pushup(now); 44 k=now; 45 return; 46 } 47 void Lt(int &k){ 48 int now=t[k].r; 49 t[k].r=t[now].l; 50 t[now].l=k; 51 pushup(k);pushup(now); 52 k=now; 53 return; 54 } 55 void DEBUG(){ 56 printf("Debug\n"); 57 for(int j=0;j<=cnt;j++){ 58 printf("#%d: lc:%d rc:%d sz:%d cnt:%d\n",j,t[j].l,t[j].r,t[j].sz,t[j].cnt); 59 } 60 printf("fin\n"); 61 return; 62 } 63 int bin[mxn*2],top=0; 64 void insert(int v,int c,int &rt){ 65 if(!rt){ 66 if(top)rt=bin[top--]; 67 else rt=++cnt; 68 t[rt].cnt=t[rt].sz=c; 69 t[rt].v=v; 70 t[rt].rand=rand(); 71 t[rt].l=t[rt].r=0; 72 return; 73 } 74 t[rt].sz+=c; 75 if(t[rt].v==v) t[rt].cnt+=c; 76 else if(v<t[rt].v){ 77 insert(v,c,t[rt].l); 78 if(t[t[rt].l].rand>t[rt].rand){ 79 Rt(rt); 80 } 81 } 82 else{ 83 insert(v,c,t[rt].r); 84 if(t[t[rt].r].rand>t[rt].rand){ 85 Lt(rt); 86 } 87 } 88 return; 89 } 90 void Merge(int &x,int &y){//y也会被改变,需要传地址 91 if(!x)return; 92 Merge(t[x].l,y); 93 Merge(t[x].r,y); 94 int tmp=x; 95 x=0; 96 insert(t[tmp].v,t[tmp].cnt,y); 97 bin[++top]=tmp; 98 return; 99 } 100 int ask_rank(int rt,int k){ 101 if(!rt)return 0; 102 if(t[t[rt].r].sz>=k)return ask_rank(t[rt].r,k); 103 else if(t[t[rt].r].sz+t[rt].cnt>=k)return t[rt].v; 104 else return ask_rank(t[rt].l,k-t[t[rt].r].sz-t[rt].cnt); 105 } 106 void link(int u,int v){ 107 u=find(u);v=find(v); 108 if(u==v)return; 109 if(t[u].sz<t[v].sz)swap(u,v); 110 Merge(rot[v],rot[u]);//v向u合并 111 fa[v]=u; 112 return; 113 } 114 int n,m,Q; 115 int h[mxn],ans[mxn*5]; 116 117 void solve(){ 118 int i,j; 119 srand(19260817); 120 for(i=1;i<=n;i++){ 121 insert(h[i],1,rot[i]); 122 }//treap init 123 int hd=1; 124 for(i=1;i<=Q;i++){ 125 while(e[hd].w<=q[i].x && hd<=m){ 126 link(e[hd].x,e[hd].y); 127 hd++; 128 } 129 int x=find(q[i].v); 130 int res=ask_rank(rot[x],q[i].k); 131 if(!res)ans[q[i].id]=-1; 132 else ans[q[i].id]=res; 133 } 134 return; 135 } 136 int main(){ 137 // freopen("Input.in","r",stdin); 138 int i,j; 139 n=read();m=read();Q=read(); 140 for(i=1;i<=n;i++){ 141 h[i]=read(); 142 fa[i]=i; 143 } 144 for(i=1;i<=m;i++){ 145 e[i].x=read();e[i].y=read();e[i].w=read(); 146 } 147 for(i=1;i<=Q;i++){ 148 q[i].v=read();q[i].x=read();q[i].k=read();q[i].id=i; 149 } 150 sort(e+1,e+m+1); 151 sort(q+1,q+Q+1); 152 solve(); 153 for(i=1;i<=Q;i++){ 154 printf("%d\n",ans[i]); 155 } 156 return 0; 157 }
以上是关于Bzoj3545 [ONTAK2010]Peaks的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 3545ONTAK 2010Peaks & BZOJ 3551ONTAK 2010Peaks加强版 Kruskal重构树
bzoj3545[ONTAK2010]Peaks 线段树合并