【刷题】BZOJ 3551 [ONTAK2010]Peaks加强版

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

Sample Input

Sample Output

HINT

【数据范围】同3545

这里附上3545:

Description

在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。

Input

第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。

Output

对于每组询问,输出一个整数表示答案。

Sample Input

10 11 4
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2

Sample Output

6
1
-1
8

HINT

【数据范围】

N<=10^5, M,Q<=5*105,h_i,c,x<=109。

Solution

kruskal重构树
重构出来后要找一棵子树中权值第 \(k\) 大,用主席树维护就好了

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100000+10,MAXM=500000+10,inf=0x3f3f3f3f;
int n,m,q,e,beg[MAXN<<1],nex[MAXN<<2],to[MAXN<<2],st[MAXN<<1],ed[MAXN<<1],cnt,nt,Jie[20][MAXN<<1],h[MAXN<<1],fa[MAXN<<1],lastans,P[MAXN];
std::vector<int> V;
std::map<int,int> M;
struct node{
	int u,v,k;
	inline bool operator < (const node &A) const {
		return k<A.k;
	};
};
node side[MAXM];
#define Mid ((l+r)>>1)
#define lson l,Mid
#define rson Mid+1,r
struct ChairMan_Tree{
	int sum[MAXN<<5],lc[MAXN<<5],rc[MAXN<<5],root[MAXN<<1],cnt;
	inline void Build(int &rt,int l,int r)
	{
		sum[rt=++cnt]=0;
		if(l==r)return ;
		else Build(lc[rt],lson),Build(rc[rt],rson);
	}
	inline void Update(int &rt,int last,int l,int r,int ps)
	{
		sum[rt=++cnt]=sum[last]+1;
		lc[rt]=lc[last];
		rc[rt]=rc[last];
		if(l==r)return ;
		else
		{
			if(ps<=Mid)Update(lc[rt],lc[last],lson,ps);
			else Update(rc[rt],rc[last],rson,ps);
		}
	}
	inline int Query(int now,int last,int l,int r,int k)
	{
		if(l==r)return l;
		else
		{
			int t=sum[rc[last]]-sum[rc[now]];
			if(k<=t)return Query(rc[now],rc[last],rson,k);
			else return Query(lc[now],lc[last],lson,k-t);
		}
	}
};
ChairMan_Tree T;
#undef Mid
#undef lson
#undef rson
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
	if(!x)putchar(48);
	static int sta[45],tp;
	for(tp=0;x;x/=10)sta[++tp]=x%10;
	for(;tp;putchar(sta[tp--]^48));
	if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline int found(int x)
{
	if(fa[x]!=x)fa[x]=found(fa[x]);
	return fa[x];
}
inline void insert(int x,int y)
{
	to[++e]=y;
	nex[e]=beg[x];
	beg[x]=e;
}
inline void dfs(int x)
{
	st[x]=++nt;
	if(x<=n)T.Update(T.root[nt],T.root[nt-1],1,n,h[x]);
	else T.root[nt]=T.root[nt-1];
	for(register int i=beg[x];i;i=nex[i])
		if(to[i]==Jie[0][x])continue;
		else dfs(to[i]);
	ed[x]=nt;
}
inline void discretization()
{
	for(register int i=1;i<=n;++i)V.push_back(h[i]);
	std::sort(V.begin(),V.end());
	V.erase(std::unique(V.begin(),V.end()),V.end());
	for(register int i=0,lt=V.size();i<lt;++i)M[V[i]]=i+1,P[i+1]=V[i];
	for(register int i=1;i<=n;++i)h[i]=M[h[i]];
}
inline void init()
{
	discretization();
	cnt=n;h[0]=inf;
	for(register int i=1;i<=n+n-1;++i)fa[i]=i;
	std::sort(side+1,side+m+1);
	for(register int i=1,u,v;i<=m;++i)
	{
		u=found(side[i].u),v=found(side[i].v);
		if(u==v)continue;
		else
		{
			cnt++;h[cnt]=side[i].k;
			insert(cnt,u);insert(u,cnt);
			insert(cnt,v);insert(v,cnt);
			fa[u]=fa[v]=Jie[0][u]=Jie[0][v]=cnt;
		}
	}
	T.Build(T.root[0],1,n);
	for(register int i=1;i<=cnt;++i)
		if(!st[i])dfs(found(i));
	for(register int j=1;j<=19;++j)
		for(register int i=1;i<=cnt;++i)Jie[j][i]=Jie[j-1][Jie[j-1][i]];
}
inline int Get(int v,int x)
{
	for(register int i=19;i>=0;--i)
		if(h[Jie[i][v]]<=x)v=Jie[i][v];
	return v;
}
int main()
{
	read(n);read(m);read(q);
	for(register int i=1;i<=n;++i)read(h[i]);
	for(register int i=1,u,v,k;i<=m;++i)
	{
		read(u);read(v);read(k);
		side[i]=(node){u,v,k};
	}
	init();
	while(q--)
	{
		int v,x,k;read(v);read(x);read(k);
		if(lastans!=-1)v^=lastans,x^=lastans,k^=lastans;
		int ps=Get(v,x);
		if(ps==v||k>T.sum[T.root[ed[ps]]]-T.sum[T.root[st[ps]-1]])printf("%d\n",lastans=-1);
		else write(lastans=P[T.Query(T.root[st[ps]-1],T.root[ed[ps]],1,n,k)],'\n');
	}
	return 0;
}
posted @ 2018-08-04 10:48  HYJ_cnyali  阅读(166)  评论(0编辑  收藏  举报