bzoj3551 [ONTAK2010]Peaks加强版

Posted wfj_2048

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3551 [ONTAK2010]Peaks加强版相关的知识,希望对你有一定的参考价值。

Description

//【题目描述】同3545
在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,表示一组询问。v=v xor lastans,x=x xor lastans,k=k xor lastans。如果lastans=-1则不变。 

Output

//同3545
对于每组询问,输出一个整数表示答案。

Sample Input

Sample Output

HINT

//【数据范围】同3545
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。

 

正解:$kruskal$重构树+主席树。

这题的普通版是权限题。。

有一个神奇的东西,叫做$kruskal$重构树。

我们在做最小生成树的时候,并不是直接把两个联通块的根连起来,而是对于两个联通块,新建一个点,连向这两个联通块的根结点,而这个新建点的点权就是这条边的边权。

注意到这样做生成的树有一些性质:

1.这是一棵二叉树。

2.原树点都是叶子结点。

3.子结点比父结点点权小(大根堆)。

4.原树与新树两点间路径最大值与新树相等,且等于新树两点$lca$点权。

然后我们发现,对于任意一个$v$,我们向上找到深度最小的满足点权$<=x$的点,然后查询整个子树的第$k$大,就是答案了。

 

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cstdio>
  7 #include <vector>
  8 #include <cmath>
  9 #include <queue>
 10 #include <stack>
 11 #include <map>
 12 #include <set>
 13 #define inf (1<<30)
 14 #define N (200010)
 15 #define il inline
 16 #define RG register
 17 #define ll long long
 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
 19 
 20 using namespace std;
 21 
 22 struct edge{ int nt,to; }G[N<<1];
 23 struct E{ int u,v,w; }g[N<<2];
 24 
 25 int head[N],top[N],fa[N],son[N],dep[N],pos[N],dfn[N],ed[N],sz[N],hsh[N],h[N],d[N];
 26 int sum[20*N],ls[20*N],rs[20*N],rt[N],Sz,n,m,Q,RT,num,cnt,tot,ans;
 27 
 28 il int gi(){
 29     RG int x=0,q=1; RG char ch=getchar();
 30     while ((ch<0 || ch>9) && ch!=-) ch=getchar();
 31     if (ch==-) q=-1,ch=getchar();
 32     while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar();
 33     return q*x;
 34 }
 35 
 36 il void insert(RG int from,RG int to){
 37     G[++num]=(edge){head[from],to},head[from]=num; return;
 38 }
 39 
 40 il int cmp(const E &a,const E &b){ return a.w<b.w; }
 41 
 42 il int find(RG int x){ return (!fa[x] || fa[x]==x) ? x : fa[x]=find(fa[x]); }
 43 
 44 il void dfs1(RG int x,RG int p){
 45     fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG int v;
 46     for (RG int i=head[x];i;i=G[i].nt){
 47     v=G[i].to; if (v==p) continue;
 48     dfs1(v,x),sz[x]+=sz[v];
 49     if (sz[son[x]]<=sz[v]) son[x]=v;
 50     }
 51     return;
 52 }
 53 
 54 il void dfs2(RG int x,RG int p,RG int anc){
 55     top[x]=anc,dfn[x]=++cnt,pos[cnt]=x;
 56     if (son[x]) dfs2(son[x],x,anc); RG int v;
 57     for (RG int i=head[x];i;i=G[i].nt){
 58     v=G[i].to; if (v==p || v==son[x]) continue;
 59     dfs2(v,x,v);
 60     }
 61     ed[x]=cnt; return;
 62 }
 63 
 64 il int lca(RG int x,RG int k){
 65     RG int la=x; while (x && d[top[x]]<=k) la=top[x],x=fa[top[x]];
 66     if (d[x]>k || d[top[x]]<=k) return la;
 67     RG int l=dfn[top[x]],r=dfn[x],mid,res;
 68     while (l<=r){
 69     mid=(l+r)>>1;
 70     if (d[pos[mid]]<=k) res=pos[mid],r=mid-1; else l=mid+1;
 71     }
 72     return res;
 73 }
 74 
 75 il void add(RG int x,RG int &y,RG int l,RG int r,RG int v){
 76     sum[y=++Sz]=sum[x]+1,ls[y]=ls[x],rs[y]=rs[x];
 77     if (l==r) return; RG int mid=(l+r)>>1;
 78     v<=mid?add(ls[x],ls[y],l,mid,v):add(rs[x],rs[y],mid+1,r,v); return;
 79 }
 80 
 81 il int query(RG int x,RG int y,RG int l,RG int r,RG int k){
 82     if (l==r) return hsh[l]; RG int mid=(l+r)>>1,tmp=sum[rs[y]]-sum[rs[x]];
 83     return k<=tmp?query(rs[x],rs[y],mid+1,r,k):query(ls[x],ls[y],l,mid,k-tmp);
 84 }
 85 
 86 il void work(){
 87     n=gi(),m=gi(),Q=gi();
 88     for (RG int i=1;i<=n;++i) fa[i]=i,h[i]=gi(),hsh[++tot]=h[i];
 89     sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1;
 90     for (RG int i=1;i<=n;++i) h[i]=lower_bound(hsh+1,hsh+tot+1,h[i])-hsh;
 91     for (RG int i=1;i<=m;++i) g[i].u=gi(),g[i].v=gi(),g[i].w=gi();
 92     sort(g+1,g+m+1,cmp),cnt=n;
 93     for (RG int i=1,k=0,x,y;i<=m;++i){
 94     x=find(g[i].u),y=find(g[i].v); if (x==y) continue;
 95     fa[x]=fa[y]=++cnt,insert(cnt,x),insert(cnt,y);
 96     d[cnt]=g[i].w,RT=cnt,++k; if (k==n-1) break;
 97     }
 98     cnt=0,dfs1(RT,0),dfs2(RT,0,RT);
 99     for (RG int i=1;i<=cnt;++i)
100     if (pos[i]>n) rt[i]=rt[i-1];
101     else add(rt[i-1],rt[i],1,tot,h[pos[i]]);
102     for (RG int i=1,v,x,k,Lca;i<=Q;++i){
103     v=gi()^ans,x=gi()^ans,k=gi()^ans,Lca=lca(v,x);
104     if (sum[rt[ed[Lca]]]-sum[rt[dfn[Lca]-1]]<k) ans=0,puts("-1");
105     else ans=query(rt[dfn[Lca]-1],rt[ed[Lca]],1,tot,k),printf("%d\n",ans);
106     }
107     return;
108 }
109 
110 int main(){
111     File("peaks");
112     work();
113     return 0;
114 }

 

以上是关于bzoj3551 [ONTAK2010]Peaks加强版的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3545ONTAK 2010Peaks & BZOJ 3551ONTAK 2010Peaks加强版 Kruskal重构树

bzoj 3551: [ONTAK2010]Peaks加强版

bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增

bzoj3551 [ONTAK2010]Peaks加强版

bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)

BZOJ 3551[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树