BJ模拟 Pandaria(可持续化并查集)

Description

        Mr. Panda 有 N 个花园,编号从 1 到 N 。对于编号为 i 的花园,花园里只有一朵花,颜色为  ci  。花园与花园之间有道路连接(道路是双向的)。每条道路都有一个花费,表示经过该道路花费的时间

        Mr. Panda 喜欢在他的N个花园中转悠,然后采尽可能多的同种颜色的花。然而,有时候他并不想花太多时间走同一段路。现在问题来了,每一次 Mr. Panda 会告诉你:他从哪个花园开始出发和他能忍受的走同一段路的花费的最大值w(也就是说,只有费用不超过w的道路可以通行)。

       请你判断Mr. Panda最多能采到的花是哪种颜色的花。如果有多种颜色符合条件,选择颜色编号最小的输出。

Input

       第一行包含三个整数  N,M,type  ,分别表示花园数目、道路数目和数据是否加密。

       接下来一行N个整数,第i个整数表示第i个花园中的花的颜色

       接下来M行表示花园中的道路,每行三个整数  x,y,w  ,表示有一条花费为w的道路连接x号花园和y号花园。

       接下来一个整数Q,表示Q组询问。

       接下来Q行,每行一组询问x, w,表示Mr. Panda从x号花园出发,他能忍受的走同一段路的花费的最大值w。如果type=0,则输入给定的x和w均为真实的x和w。如果type=1,则输入给定的x和w均为加密后的x和w。设上一次询问的答案为last,则需要将x和w均与last异或后才能得到真实的x和w。特别地,对于第一组询问,last = 0。

Output

       输出Q行,每行一个整数表示Mr. Panda最多能采到的花是哪种颜色的花。如果有多种颜色符合条件,选择颜色编号最小的输出。

Sample Input

【样例输入1】
5 6 0
2 1 1 3 2
1 2 2
1 3 4
2 3 7
3 4 5
4 5 6
5 3 3
4
1 1
2 2
4 4
5 8
【样例输入2】
5 6 1
2 1 1 3 2
1 2 2
1 3 4
2 3 7
3 4 5
4 5 6
5 3 3
4
1 1
0 0
5 5
6 11

Sample Output

【样例输出1】
2
1
3
1
【样例输出2】
2
1
3
1

HINT

【样例解释】

第二组数据解密后即是第一组数据。

第一组询问:没有路可以走,故从1号点只能采颜色2的花1朵,故答案为2。

第二组询问:第1条路可以走,故从2号点开始可以采颜色1的花1朵,颜色2的花1朵,故答案为1。

第三组询问:第1、2、6条路可以走,故从4号点开始可以采颜色3的花1朵,故答案为3。

第四组询问:所有路都可以走,故从5号点开始可以采颜色1的花2朵,颜色2的花2朵,颜色3的花1朵,故答案为1。

【数据范围与约定】

本题设有5个测试点。

第1个测试点:  N2×103,M,Q4×103,type=1

第2个测试点:  N5×104,M,Q1×105,type=0

第3个测试点:  N1×105,M,Q2×105,type=0

第4个测试点:  N5×104,M,Q1×105,type=1

第5个测试点:  N1×105,M,Q2×105,type=1

对于所有数据:

1N105

1M,Q2×105

1x,y,ciN

1w106


解法:可持久化并查集、可持久化线段树。

考虑Kruscal的过程,合并两个节点时,新建一个节点后把原来的节点视为新节点的左右儿子。

这样可以建出一个树,每次询问相当于询问这棵树上一个子树颜色的众数。线段树合并(启发式合并)即可。


代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
const int Maxn=1e6+50;
const int Maxm=5e6+50;
const int INF=0x3f3f3f3f;
inline int read()
{
	char ch=getchar();int i=0,f=1;
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
	return i*f;
}
struct tr
{
	int lc,rc;
	pair<int,int >mx;
}tr[Maxm];
int n,m,type,cnt,last,num[Maxn];
int father[Maxn],fw[Maxn],sze[Maxm],rt[Maxn];
struct node
{
	int x,y,w;
	friend inline bool operator <(const node &a,const node &b)
	{
		return a.w<b.w;
	}
}edge[Maxn];
map<int,int>to[Maxn];
inline int getf(int x,int w=INF)
{
	if(father[x]==x||w<fw[x])return x;
	return getf(father[x],w);
}
inline int Merge(int l,int r,int x1,int x2)
{
	if(!x1)return x2;
	if(!x2)return x1;
	int x=++cnt;
	if(l==r)tr[x].mx=make_pair(tr[x1].mx.first+tr[x2].mx.first,tr[x1].mx.second);
	else
	{
		int mid=(l+r)>>1;
		tr[x].lc=Merge(l,mid,tr[x1].lc,tr[x2].lc);
		tr[x].rc=Merge(mid+1,r,tr[x1].rc,tr[x2].rc);
		tr[x].mx=max(tr[tr[x].lc].mx,tr[tr[x].rc].mx);
	}
	return x;
}
inline int Build(int l,int r,int val)
{
	int x=++cnt;
	tr[x].mx=make_pair(1,-val);
	if(l!=r)
	{
		int mid=(l+r)>>1;
		if(val<=mid)
		tr[x].lc=Build(l,mid,val);
		else tr[x].rc=Build(mid+1,r,val);
	}
	return x;
}
inline int Query(int x,int w)
{
	int f=getf(x,w);
	auto it=to[f].upper_bound(w);
	it--;
	return -tr[it->second].mx.second;
}
int main()
{
	//freopen("lx.in","r",stdin);
	n=read(),m=read(),type=read();
	for(int i=1;i<=n;i++)
	{
		num[i]=read();
		father[i]=i;
		fw[i]=0;
		sze[i]=1;
		to[i][0]=rt[i]=Build(1,n,num[i]);
	}
	for(int i=1;i<=m;i++)
	{
		edge[i].x=read(),edge[i].y=read(),edge[i].w=read();
	}
	sort(edge+1,edge+m+1);
	for(int i=1;i<=m;i++)
	{
		int x=edge[i].x,y=edge[i].y,w=edge[i].w;
		x=getf(x),y=getf(y);
		if(x!=y)
		{
			if(sze[x]<sze[y])swap(x,y);
			father[y]=x;sze[x]+=sze[y];fw[y]=w;
			to[x][w]=rt[x]=Merge(1,n,rt[x],rt[y]);
		}
	}
	m=read();
	while(m--)
	{
		int x=read(),w=read();
		if(type)x^=last,w^=last;
		printf("%d\n",last=Query(x,w));
	}
}




  
  
   
   

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值