洛谷P4197 Peaks&&克魯斯卡爾重構樹學習筆記(克魯斯卡爾重構樹+主席樹)

傳送門html

 

聽說離線作法是主席樹上樹+啓發式合併(然而我並不會)node

聽說bzoj上有強制在線版本只能用克魯斯卡爾重構樹,那就好好講一下好了ios

這裏先感謝LadyLex大佬的博客->這裏git

克魯斯卡爾重構樹能夠用來解決一類諸如「查詢從某個點出發通過邊權不超過val的邊所能到達的節點」的問題spa

首先不難發現,上面這個問題確定是在最小生成樹上走最優,其餘邊均可以不用去管code

那麼咱們就在建最小生成樹的時候搞事情htm

克魯斯卡爾重構樹的思想就是在建最小生成樹的時候不是直接連邊,而是新建一個節點,並把這個節點的值設爲邊權,而後令兩個連通塊的表明點分別做爲它的左右兒子。而後令這個新節點成爲整個連通塊的表明點blog

說了那麼多跟沒說同樣……舉個栗子好了排序

假設如今有四個節點,要求他們的克魯斯卡爾重構樹get

咱們按最小生成樹的方法找,先把邊按權值從小到大排序。

而後設第一條邊權值爲4,鏈接1和2這兩個連通塊

而後新建一個節點5,點權設爲4,並把1和2做爲他的左右兒子

第二條邊權值爲6,鏈接3和4這兩個連通塊

而後新建一個節點6,點權設爲6,並把3和4做爲他的左右兒子

第三條邊權值爲7,鏈接1和2,那麼咱們就是要把4和6的連通塊相連了(這兩個是連通塊的表明點)

而後新建一個節點7,點權設爲7,並把5和6做爲他的左右兒子

而後這一棵克魯斯卡爾重構樹就建好了٩(๑>◡<๑)۶

不難發現它有一個性質,每個兒子節點的權值都小於等於本身的權值(由於咱們是按最小生成樹的順序建的)

那麼要查「查詢從某個點出發通過邊權不超過val的邊所能到達的節點」

由於咱們一個原來圖上的點確定是葉子結點,因此咱們只要從葉子結點開始往上找,直到找到最後一個點權小於等於$val$的點

那麼這個點爲根的子樹裏的全部點都能到達

怎麼找呢?倍增就好了

放到這一題裏,由於要查詢第$k$大,因此還得套個主席樹上樹

然而就差很少了

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 8 char buf[1<<21],*p1=buf,*p2=buf;
 9 inline int read(){
10     #define num ch-'0'
11     char ch;bool flag=0;int res;
12     while(!isdigit(ch=getc()))
13     (ch=='-')&&(flag=true);
14     for(res=num;isdigit(ch=getc());res=res*10+num);
15     (flag)&&(res=-res);
16     #undef num
17     return res;
18 }
19 char sr[1<<21],z[20];int C=-1,Z;
20 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
21 inline void print(int x){
22     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
23     while(z[++Z]=x%10+48,x/=10);
24     while(sr[++C]=z[Z],--Z);sr[++C]='\n';
25 }
26 const int N=2e5+5,M=N*16,K=5e5+5;
27 struct node{
28     int from,to,cost;
29     node(){}
30     node(int from,int to,int cost):from(from),to(to),cost(cost){}
31     inline bool operator <(const node &b)const
32     {return cost<b.cost;}
33 }E[K];
34 int head[N],Next[N],ver[N],sum[M],L[M],R[M],bin[25],cnt,tot;
35 int fa[N],f[N][20],ls[N],rs[N],rt[N],val[N],num;
36 int h[N],limit,b[N],n,q,m,ans=0,dfn;
37 inline void mission(int u){
38     for(int i=1;bin[i]<=n;++i)
39     f[u][i]=f[f[u][i-1]][i-1];
40 }
41 inline void add(int u,int v){
42     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
43 }
44 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
45 void update(int last,int &now,int l,int r,int x){
46     sum[now=++cnt]=sum[last]+1;
47     if(l==r) return;
48     int mid=(l+r)>>1;
49     if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
50     else L[now]=L[last],update(R[last],R[now],mid+1,r,x);
51 }
52 int query(int a,int x,int k){
53     int l=1,r=limit;
54     for(int j=18;~j;--j)
55     if(f[a][j]&&val[f[a][j]]<=x) a=f[a][j];
56     int v=rt[rs[a]],u=rt[ls[a]-1];
57     if(sum[v]-sum[u]<k) return -1;
58     while(l<r){
59         int tmp=sum[R[v]]-sum[R[u]],mid=(l+r)>>1;
60         if(tmp>=k) v=R[v],u=R[u],l=mid+1;
61         else v=L[v],u=L[u],r=mid,k-=tmp;
62     }
63     return b[r];
64 }
65 void dfs(int u){
66     mission(u),ls[u]=++num;
67     if(u<=n) update(rt[num-1],rt[num],1,limit,h[u]);
68     else rt[num]=rt[num-1];
69     for(int i=head[u];i;i=Next[i]) dfs(ver[i]);
70     rs[u]=num;
71 }
72 int main(){
73 //    freopen("testdata.in","r",stdin);
74     n=read(),m=read(),q=read();
75     bin[0]=1;for(int i=1;i<=22;++i) bin[i]=bin[i-1]<<1;
76     for(int i=1;i<=2*n;++i) fa[i]=i;
77     for(int i=1;i<=n;++i) b[i]=h[i]=read();
78     for(int i=1,u,v,e;i<=m;++i)
79     u=read(),v=read(),e=read(),E[i]=node(u,v,e);
80     sort(b+1,b+1+n),limit=unique(b+1,b+1+n)-b-1;
81     for(int i=1;i<=n;++i) h[i]=lower_bound(b+1,b+1+limit,h[i])-b;
82     sort(E+1,E+1+m);dfn=n;
83     for(int i=1;i<=m;++i){
84         int u=find(E[i].from),v=find(E[i].to);
85         if(u!=v){
86             val[++dfn]=E[i].cost,fa[u]=fa[v]=dfn;
87             add(dfn,u),add(dfn,v),f[u][0]=f[v][0]=dfn;
88             if(dfn-n==n-1) break;
89         }
90     }
91     for(int i=1;i<=dfn;++i) if(!ls[i]) dfs(find(i));
92     while(q--){
93         int v=read(),x=read(),k=read();
94         print(query(v,x,k));
95     }
96     Ot();
97     return 0;
98 }
相關文章
相關標籤/搜索