bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)相关的知识,希望对你有一定的参考价值。
Description
【题目描述】同3545
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
【思路】
Kruskal+主席树+dfs序
一个叫kruskal重构树的方法QWQ。在kruskal合并子树的时候新建一个ext结点,然后让它成为两棵子树公共的根,赋边权为权值。
新建成的树的性质:
对于一个询问,我们找到v的点权值不超过x的最小祖先,以该祖先为根的子树中所有的点与v都满足条件,然后就是在一个子树中找到第k大的问题,可以基于dfs序建主席树处理。
【代码】
1 #include<cstdlib> 2 #include<queue> 3 #include<vector> 4 #include<cstdio> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 9 using namespace std; 10 11 typedef long long ll; 12 const int N = 200005; 13 const int M = 5100005; 14 const int D = 17; 15 16 struct Edge { 17 int u,v,w; 18 bool operator < (const Edge& rhs) const { 19 return w<rhs.w; 20 } 21 }; 22 struct LEdge { int v,nxt; 23 }; 24 struct Tnode{ 25 int lc,rc,sum; 26 }T[M]; 27 28 ll read() { 29 char c=getchar(); 30 ll f=1,x=0; 31 while(!isdigit(c)) { 32 if(c==‘-‘) f=-1; c=getchar(); 33 } 34 while(isdigit(c)) 35 x=x*10+c-‘0‘,c=getchar(); 36 return x*f; 37 } 38 39 int n,m,q,sz,tot,dfsc; 40 int hash[N],h[N],rt[N],val[N],bin[N]; 41 int p[N],dep[N],fa[N][D],mx[N][D],L[N],R[N]; 42 43 Edge es[N<<1]; LEdge e[N<<1]; 44 int en=-1,front[N]; 45 void adde(int u,int v) 46 { 47 en++; e[en].v=v; e[en].nxt=front[u]; front[u]=en; 48 } 49 int ifind(int u) 50 { 51 return u==p[u]? u: p[u]=ifind(p[u]); 52 } 53 void update(int l,int r,int x,int& y,int num) 54 { 55 T[y=++sz]=T[x]; 56 T[y].sum++; 57 if(l>=r) return ; 58 int mid=(l+r)>>1; 59 if(num<=mid) update(l,mid,T[x].lc,T[y].lc,num); 60 else update(mid+1,r,T[x].rc,T[y].rc,num); 61 } 62 int query(int l,int r,int a,int b,int rk) 63 { 64 int mid=(l+r)>>1; 65 if(l>=r) return mid; 66 int now=T[T[b].rc].sum-T[T[a].rc].sum; 67 if(rk<=now) return query(mid+1,r,T[a].rc,T[b].rc,rk); 68 else return query(l,mid,T[a].lc,T[b].lc,rk-now); 69 } 70 void dfs(int u) 71 { 72 L[u]=++dfsc; 73 update(0,tot,rt[L[u]-1],rt[L[u]],h[u]); 74 FOR(i,1,D-1) { 75 fa[u][i]=fa[fa[u][i-1]][i-1]; 76 mx[u][i]=max(mx[u][i-1],mx[fa[u][i-1]][i-1]); 77 } 78 for(int i=front[u];i>=0;i=e[i].nxt) { 79 int v=e[i].v; 80 dep[v]=dep[u]+1, 81 dfs(v); 82 } 83 R[u]=dfsc; 84 } 85 int find_root(int u,int x) 86 { 87 for(int i=D-1;i>=0;i--) 88 if(fa[u][i] && mx[u][i]<=x) 89 u=fa[u][i]; 90 return u; 91 } 92 93 int main() 94 { 95 //reopen("in.in","r",stdin); 96 //freopen("out.out","w",stdout); 97 98 memset(front,-1,sizeof(front)); 99 n=read(),m=read(),q=read(); 100 FOR(i,1,n) h[i]=read(),hash[i]=h[i]; 101 int u,v,w,x,k,ans=0; 102 FOR(i,1,m) { 103 u=read(),v=read(),w=read(); 104 es[i]=(Edge){u,v,w}; 105 } 106 107 FOR(i,1,2*n) p[i]=i; 108 sort(hash+1,hash+n+1); 109 tot=unique(hash+1,hash+n+1)-hash-1; 110 FOR(i,1,n) 111 h[i]=lower_bound(hash+1,hash+tot+1,h[i])-hash; 112 113 sort(es+1,es+m+1); 114 FOR(i,1,m) { 115 Edge e=es[i]; 116 int x=ifind(e.u),y=ifind(e.v); 117 if(x!=y) { 118 int ext=++n; 119 fa[x][0]=fa[y][0]=ext; 120 mx[x][0]=mx[y][0]=e.w; 121 p[x]=p[y]=ext; 122 adde(ext,x),adde(ext,y); 123 } 124 } 125 126 dfs(n); 127 128 FOR(i,1,q) { 129 v=read(),x=read(),k=read(); 130 v^=ans,x^=ans,k^=ans; 131 int root=find_root(v,x); 132 if(R[root]-L[root]+1<k) puts("-1"),ans=0; 133 else { 134 ans=query(0,tot,rt[L[root]-1],rt[R[root]],k); 135 if(!ans) puts("-1"); 136 else printf("%d\n",ans=hash[ans]); 137 } 138 } 139 return 0; 140 }
以上是关于bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj3545/bzoj3551 [ONTAK2010]Peaks/Peaks加强版
bzoj 3551: [ONTAK2010]Peaks加强版
bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增