[BZOJ3551][ONTAK2010]Peaks加强版

description

题面

data range

\[n\le 100000,m,k\le500000 \]

solution

\(Kruskal\)重构树可以十分便捷的求出从一个点出发,只能经过边权不超过\(v\)的点所能到达的点集

重构树的构建通过并查集连边时实现

\(Krusakl\)重构树中,从一个点出发,只能经过边权不超过\(v\)的点所能到达的点集是一棵子树

因此做主席树求第子树\(k\)大即可

code

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define FILE "a"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=200010;
const int M=500010;
const dd pi=acos(-1);
const int inf=2147483645;
const ll INF=1e18+1;
const ll P=100000;
il ll read(){
	RG ll data=0,w=1;RG char ch=getchar();
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
	return data*w;
}

il void file(){
	srand(time(NULL)+rand());
	freopen("1.in","r",stdin);
	freopen(FILE".out","w",stdout);
}

int n,m,q,num,h[N],ans;
int len,o[N],p[N];
struct edge{int u,v,w;}E[M];
bool cmp_w(edge x,edge y){return x.w<y.w;}

int fa[N],RT,val[N];
int find(int u){return fa[u]?fa[u]=find(fa[u]):u;}

int head[N],nxt[N<<1],to[N<<1],cnt;
il void add(int u,int v){to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;}

int rt[N],sum[20*N],s[2][20*N],tot;
#define mid ((l+r)>>1)
void insert(int &i,int pre,int l,int r,int k){
	i=++tot;sum[i]=sum[pre]+1;s[0][i]=s[0][pre];s[1][i]=s[1][pre];
	if(l==r)return;
	if(k<=mid)insert(s[0][i],s[0][pre],l,mid,k);
	else insert(s[1][i],s[1][pre],mid+1,r,k);
}
il int query(int L,int R,int l,int r,int k){
	if(l==r)return l;
	RG int S=sum[s[0][R]]-sum[s[0][L]];
	if(k<=S)return query(s[0][L],s[0][R],l,mid,k);
	else return query(s[1][L],s[1][R],mid+1,r,k-S);
}

int f[20][N],dfn[N],sz[N],cntw;
void dfs(int u,int ff){
	dfn[u]=++cntw;sz[u]=1;f[0][u]=ff;
	for(RG int i=1;f[i-1][f[i-1][u]];i++)f[i][u]=f[i-1][f[i-1][u]];
	if(u<=n)insert(rt[dfn[u]],rt[dfn[u]-1],1,len,p[u]);
	else rt[dfn[u]]=rt[dfn[u]-1];
	for(RG int i=head[u];i;i=nxt[i]){
		RG int v=to[i];dfs(v,u);sz[u]+=sz[v];
	}
}

il int solve(int v,int x,int k){
	RG int u=v;
	for(RG int i=19;~i;i--)
		if(f[i][u]&&val[f[i][u]]<=x)u=f[i][u];
	RG int S=sum[rt[dfn[u]+sz[u]-1]]-sum[rt[dfn[u]-1]];
	if(S<k)return -1;
	else return o[query(rt[dfn[u]-1],rt[dfn[u]+sz[u]-1],1,len,S-k+1)];
}

int main()
{
	num=n=read();m=read();q=read();
	for(RG int i=1;i<=n;i++)o[i]=h[i]=read(),sz[i]=1;
	sort(o+1,o+n+1);len=unique(o+1,o+n+1)-o-1;
	for(RG int i=1;i<=n;i++)p[i]=lower_bound(o+1,o+len+1,h[i])-o;
	for(RG int i=1,u,v,w;i<=m;i++){
		u=read();v=read();w=read();E[i]=(edge){u,v,w};
	}
	sort(E+1,E+m+1,cmp_w);
	for(RG int i=1;i<=m;i++)
		if(find(E[i].u)!=find(E[i].v)){
			RG int x=find(E[i].u),y=find(E[i].v);
			val[++num]=E[i].w;
			fa[x]=fa[y]=num;add(num,x);add(num,y);
		}
	
	RT=find(1);dfs(RT,0);
	for(RG int i=1,v,x,k;i<=q;i++){
		v=read();x=read();k=read();
		if(~ans)v^=ans,x^=ans,k^=ans;
		printf("%d\n",ans=solve(v,x,k));
	}
	return 0;
}

posted @ 2018-08-18 21:44  cjfdf  阅读(171)  评论(0编辑  收藏  举报