[BZOJ3551]Peaks加强版

题目大意:见https://www.cnblogs.com/Mrsrz/p/9354136.html

强制在线

解题思路:
Kruskal重构树。
我们从小到大加入边,每次合并两个连通块时,新建一个节点作为它们的父亲,点权为原来的边权。
然后对于每个询问,倍增找最上方的点权不超过x的点,则该点构成的子树上的所有叶子节点就是原来的点能到的所有节点。
于是对每棵子树建主席树,查询时就是在子树内查询第k大。建主席树时相当于线段树合并。
C++ Code:

#include<bits/stdc++.h>
#define N 100005
template<typename T>
inline void read(T&d){
	d=0;static int c;
	for(c=getchar();!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^'0');
}
struct edge{
	int u,v,dis;
	inline bool operator<(const edge&rhs)const{return dis<rhs.dis;}
}E[N*5];
struct Edge{
	int to,nxt;
}e[N<<3];
struct segmentTreeNode{
	int s,ls,rs;
}d[6000005];
int n,m,q,h[N],fa[N<<1],nodes,f[N<<1][19],cnt=0,dang[N<<1],head[N<<1],hh[N],rt[N<<1];
int treenode=0;
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void init(int l,int r,int&o,int p){
	o=++treenode;
	d[o].s=1;
	if(l==r)return;
	int mid=l+r>>1;
	if(p<=mid)init(l,mid,d[o].ls,p);else
	init(mid+1,r,d[o].rs,p);
}
int merge(int ls,int rs){
	if(!ls||!rs)return ls|rs;
	int nw=++treenode;
	if(!d[ls].ls&&!d[ls].rs){
		d[nw].s=d[ls].s+d[rs].s;
		return nw;
	}
	d[nw].ls=merge(d[ls].ls,d[rs].ls);
	d[nw].rs=merge(d[ls].rs,d[rs].rs);
	d[nw].s=d[d[nw].ls].s+d[d[nw].rs].s;
	return nw;
}
void dfs(int now){
	for(int i=head[now];i;i=e[i].nxt){
		dfs(e[i].to);
		if(!rt[now])rt[now]=rt[e[i].to];else
		rt[now]=merge(rt[now],rt[e[i].to]);
	}
	if(!head[now])
	init(0,N,rt[now],hh[now]);
}
int query(int l,int r,int&o,int k){
	if(l==r)return l;
	int mid=l+r>>1;
	if(d[d[o].rs].s>=k)return query(mid+1,r,d[o].rs,k);
	return query(l,mid,d[o].ls,k-d[d[o].rs].s);
}
int main(){
	read(n),read(m),read(q);
	for(int i=1;i<=n;++i)read(h[i]),hh[i]=h[i];
	std::sort(h+1,h+n+1);
	int nn=std::unique(h+1,h+n+1)-h-1;
	for(int i=1;i<=n;++i)hh[i]=std::lower_bound(h+1,h+nn+1,hh[i])-h;
	for(int i=1;i<=m;++i)read(E[i].u),read(E[i].v),read(E[i].dis);
	std::sort(E+1,E+m+1);
	for(int i=1;i<=n;++i)fa[i]=i,fa[i+n]=i+n;
	nodes=n;
	for(int less_node=n-1,i=1;less_node&&i<=m;++i){
		int x=find(E[i].u),y=find(E[i].v);
		if(x!=y){
			fa[x]=fa[y]=f[x][0]=f[y][0]=++nodes;
			dang[nodes]=E[i].dis;
			--less_node;
			e[++cnt]=(Edge){x,head[nodes]};
			head[nodes]=cnt;
			e[++cnt]=(Edge){y,head[nodes]};
			head[nodes]=cnt;
		}
	}
	dang[0]=0x3f3f3f3f;
	memset(d,0,sizeof d);
	dfs(nodes);
	for(int j=1;j<19;++j)
	for(int i=1;i<=nodes;++i)
	f[i][j]=f[f[i][j-1]][j-1];
	int ans=0;
	while(q--){
		int u,x,k;
		read(u),read(x),read(k);
		u^=ans,x^=ans,k^=ans;
		for(int i=18;~i;--i)if(dang[f[u][i]]<=x)u=f[u][i];
		if(d[rt[u]].s<k)puts("-1"),ans=0;else
		printf("%d\n",ans=h[query(0,N,rt[u],k)]);
	}
	return 0;
}

 

posted @ 2018-07-23 17:12  Mrsrz  阅读(196)  评论(0编辑  收藏  举报