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 -- 主席树,最小生成树,倍增