1. 程式人生 > >2018.09.30 bzoj3551:Peaks加強版(dfs序+主席樹+倍增+kruskal重構樹)

2018.09.30 bzoj3551:Peaks加強版(dfs序+主席樹+倍增+kruskal重構樹)

傳送門 一道考察比較全面的題。

這道題又用到了熟悉的kruskal+倍增來查詢詢問區間的方法。 查到詢問的子樹之後就可以用dfs序+主席樹統計答案了。 程式碼:

#include<bits/stdc++.h>
#define N 200005
#define M 500005
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48
),ch=getchar(); return ans; } inline void write(int x){ if(x>9)write(x/10); putchar((x%10)^48); } int n,m,Q,h[N],val[N],fa[N],cnt=0,first[N],rt[N*3],num,son[N*25][2],siz[N*25],sz=0,st[N][20],w[N],mx[N][20],dep[N],q[N*3],bg[N],ed[N],top=0,lastans; bool vis[N]; struct node{int u,v,w;}tt[M]; struct edge{
int v,next;}e[N]; inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} inline int cmp(node a,node b){return a.w<b.w;} inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;} inline void update(int&p,int las,int l,int r,int v){ p=++sz,siz[p]=siz[las]+1; if(l==r)
return; son[p][0]=son[las][0],son[p][1]=son[las][1]; int mid=l+r>>1; if(v<=mid)update(son[p][0],son[las][0],l,mid,v); else update(son[p][1],son[las][1],mid+1,r,v); } inline int query(int a,int b,int l,int r,int k){ if(l==r)return l; int mid=l+r>>1; if(siz[son[b][0]]-siz[son[a][0]]>=k)return query(son[a][0],son[b][0],l,mid,k); return query(son[a][1],son[b][1],mid+1,r,k-siz[son[b][0]]+siz[son[a][0]]); } inline int Find(int x,int v){ for(int i=17;~i;--i)if(dep[x]>=(1<<i)&&mx[x][i]<=v)x=st[x][i]; return x; } inline void dfs(int p){ q[++top]=p,vis[p]=1; for(int i=1;(1<<i)<=dep[p];++i)st[p][i]=st[st[p][i-1]][i-1],mx[p][i]=max(mx[p][i-1],mx[st[p][i-1]][i-1]); for(int i=first[p];i;i=e[i].next){ int v=e[i].v; dep[v]=dep[p]+1,mx[v][0]=w[p],st[v][0]=p,dfs(v); } if(p>n)q[++top]=p; } inline void kruskal(){ sort(tt+1,tt+m+1,cmp); for(int i=1;i<=n*2;++i)fa[i]=i; for(int i=1;i<=m;++i){ int fx=find(tt[i].u),fy=find(tt[i].v); if(fx!=fy)fa[fx]=fa[fy]=++num,w[num]=tt[i].w,add(num,fx),add(num,fy); if(num==n*2-1)break; } for(int i=1;i<=n;++i)if(!vis[i])dfs(find(i)); for(int i=1;i<=top;++i){ int tmp=q[i]; if(tmp<=n)update(rt[i],rt[i-1],1,n,h[tmp]); else{ rt[i]=rt[i-1]; if(!bg[tmp])bg[tmp]=i; else ed[tmp]=i; } } } int main(){ n=read(),m=read(),Q=read(),lastans=-1,num=n; for(int i=1;i<=n;++i)val[i]=h[i]=read(); sort(val+1,val+n+1); for(int i=1;i<=n;++i)h[i]=lower_bound(val+1,val+n+1,h[i])-val; for(int i=1;i<=m;++i)tt[i].u=read(),tt[i].v=read(),tt[i].w=read(); kruskal(); while(Q--){ int v=read(),x=read(),k=read(); if(~lastans)v^=lastans,x^=lastans,k^=lastans; int Rt=Find(v,x),ql=rt[bg[Rt]],qr=rt[ed[Rt]]; if(siz[qr]-siz[ql]<k)puts("-1"),lastans=-1; else lastans=val[query(ql,qr,1,n,siz[qr]-siz[ql]-k+1)],printf("%d\n",lastans); } return 0; }