[Kruskal重构树][主席树] Luogu P4197 Peaks
Posted maximumhanyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Kruskal重构树][主席树] Luogu P4197 Peaks相关的知识,希望对你有一定的参考价值。
给一个 N 个点的无向图,每个点有一个高度,每条边有一个困难度。
多次询问求从 Vi 出发,只经过困难度小于等于 Xi 的边所能到达的点中第 K 高的点。
Kruskal 重构树真是个好东西,既好写又好用。
这道题把树建出来后就变成了求某个点的叶子结点中第 K 大的点。
上面说的某个点就是 Vi 在树中向上跳能跳到的点权 <= Xi 的点,
这个东西显然可以用倍增来求。
因为是求第 K 大,所以还要套一个主席树。
1 #include<bits/stdc++.h> 2 #define rep(i,a,b) for(register int i=a;i<=b;++i) 3 #define rpd(i,a,b) for(register int i=a;i>=b;--i) 4 #define rep1(i,x) for(register int i=head[x];i;i=nxt[i]) 5 typedef long long ll; 6 const int N=5e5+5,M=5e5+5; 7 using namespace std; 8 inline int read() 9 int x=0,f=1;char ch=getchar(); 10 while(!isdigit(ch))if(ch==‘-‘)f=-1;ch=getchar(); 11 while(isdigit(ch))x=x*10+ch-‘0‘;ch=getchar(); 12 return x*f; 13 14 struct edgeint x,y,z;e[M]; 15 bool cmp(edge i,edge j)return i.z<j.z; 16 int n,m,Q,tot,cnt,sum,rt; 17 int H[N],bing[N<<1],head[N<<1],to[N<<1],nxt[N<<1],w[N<<1],h[N],Ls[N],Rs[N]; 18 void add(int u,int v)nxt[++tot]=head[u];head[u]=tot;to[tot]=v; 19 int get(int x)return bing[x]==x?x:bing[x]=get(bing[x]); 20 void buildkt() 21 rep(i,1,n<<1)bing[i]=i; 22 sort(e+1,e+m+1,cmp);cnt=n; 23 rep(i,1,m) 24 int x=get(e[i].x),y=get(e[i].y),z=e[i].z; 25 if(x==y)continue; 26 w[++cnt]=z;add(cnt,x);add(cnt,y); 27 bing[x]=bing[y]=cnt; 28 if(cnt==(n<<1)-1)break; 29 30 31 int f[N][25],hs[N],id[N]; 32 void dfs(int x,int fa) 33 f[x][0]=fa;Ls[x]=n+1;Rs[x]=0; 34 if(x<=n)h[++sum]=H[x];Ls[x]=Rs[x]=sum;return; 35 rep1(i,x) 36 int p=to[i];dfs(p,x); 37 Ls[x]=min(Ls[x],Ls[p]); 38 Rs[x]=max(Rs[x],Rs[p]); 39 40 41 void init()rep(j,1,17)rep(i,1,(n<<1)-1)f[i][j]=f[f[i][j-1]][j-1]; 42 int work(int start,int dis)rpd(i,17,0)int k=f[start][i];if(k==0||w[k]>dis)continue;start=k;return start; 43 struct Treeint x,l,r;t[N<<5];int ban[N]; 44 void up(int k)t[k].x=t[t[k].l].x+t[t[k].r].x; 45 void build(int &k,int l,int r)k=++rt;if(l==r)return;int mid=l+r>>1;build(t[k].l,l,mid);build(t[k].r,mid+1,r); 46 void change(int k,int &k1,int l,int r,int p) 47 k1=++rt;t[k1]=t[k];if(l==r)t[k1].x+=1;return; 48 int mid=l+r>>1; 49 if(mid>=p)change(t[k].l,t[k1].l,l,mid,p); 50 else change(t[k].r,t[k1].r,mid+1,r,p); 51 up(k1); 52 53 int find(int k,int k1,int l,int r,int p) 54 if(l==r)return hs[l]; 55 int mid=l+r>>1,opt=t[t[k1].r].x-t[t[k].r].x; 56 if(opt>=p)return find(t[k].r,t[k1].r,mid+1,r,p); 57 return find(t[k].l,t[k1].l,l,mid,p-opt); 58 59 int main() 60 n=read();m=read();Q=read(); 61 rep(i,1,n)H[i]=read(); 62 rep(i,1,m)e[i].x=read(),e[i].y=read(),e[i].z=read(); 63 buildkt();dfs((n<<1)-1,0);init(); 64 rep(i,1,n)hs[i]=h[i];sort(hs+1,hs+n+1); 65 rep(i,1,n)id[i]=lower_bound(hs+1,hs+n+1,h[i])-hs; 66 build(ban[0],1,n); 67 rep(i,1,n)change(ban[i-1],ban[i],1,n,id[i]); 68 //rep(i,1,n)cout<<i<<‘ ‘<<h[i]<<endl; 69 while(Q--) 70 int v=read(),x=read(),k=read(),root=work(v,x),L=Ls[root],R=Rs[root]; 71 //cout<<L<<‘ ‘<<R<<endl; 72 if(k>R-L+1)puts("-1");continue; 73 printf("%d\n",find(ban[L-1],ban[R],1,n,k)); 74 75 //system("pause"); 76 return 0; 77
以上是关于[Kruskal重构树][主席树] Luogu P4197 Peaks的主要内容,如果未能解决你的问题,请参考以下文章
[IOI2018] werewolf 狼人 kruskal重构树,主席树