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

bzoj3551 [ONTAK2010]Peaks加强版

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

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