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
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个测试点: N≤2×103,M,Q≤4×103,type=1
第2个测试点: N≤5×104,M,Q≤1×105,type=0
第3个测试点: N≤1×105,M,Q≤2×105,type=0
第4个测试点: N≤5×104,M,Q≤1×105,type=1
第5个测试点: N≤1×105,M,Q≤2×105,type=1
对于所有数据:
1≤N≤105
1≤M,Q≤2×105
1≤x,y,ci≤N
1≤w≤106
解法:可持久化并查集、可持久化线段树。
考虑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));}
}
BJ模拟 Pandaria(可持续化并查集)相关推荐
- NOI模拟 : Vain (并查集维护割点)
题意: 对于 1 ≤ i ≤ n, 求出点 i 度数强制为 1 的情况下最小生成树的最大边的权值. 题解: 相当于求出删掉每个点之后的MSTMSTMST的最大值. 我们按边的权值从小到大加入新图, 很 ...
- Gym - 101194G Pandaria (并查集+倍增+线段树合并)
题意: 给定一个无向图.每个点有一种颜色.现在给定q个询问,每次询问x和w,求所有能通过边权值不超过w的边走到x的点的集合中,哪一种颜色的点出现的次数最多.次数相同时输出编号最小的那个颜色.强制在线. ...
- [kuangbin带你飞]专题五 并查集 题解+总结
kuangbin带你飞:点击进入新世界 总结: 本人算是初学者中的初学者,欢迎交流~ 并查集的接触过的不多,大概只有普通并查集,带权并查集,种族并查集,传说中的可持续化并查集只是听说过还没有接触,不过 ...
- 并查集 ---- 扩展域并查集判二分图 + 循环模拟字典树 The 2020 ICPC Asia Macau Regional Contest C. Club Assignment (详解)
题目链接 题目大意: 有n个数,现在要把他们拆分成两个集合,假设S为集合,有如下定义: f(S)={min(x⊕y)∣x,y∈S,andx!=y}f(S)=\{min(x\oplus y)|x,y\i ...
- HDU-3974 Assign the task 线段树 或 直接模拟多叉树 或 并查集 (三种方法)
题目大意 t 组数据(t<=10),每组第一行一个 n 表示 n 个员工(n<=5e4),接下来 n-1 行,每行两个整数 u,v 表示 v 是 u 的上司 然后一行 m 表示有 m 个操 ...
- 并查集是什么?怎么模拟实现?如何应用?
目录 一.什么是并查集? 二.并查集可以解决哪些问题? 三.并查集的模拟实现 3.1.并查集的定义 3.2.查询两个元素是否是同一个集合 3.3.合并两个集合 3.4.求集合个数 3.5.并查集完整代 ...
- Day10 堆排序、模拟堆 trie树(字典树) 并查集
堆呢就是一棵树完全二叉树... 小根堆的话,根节点就是最小值 维护堆只有两个操作 up(k) down(k) cnt是堆的大小 建堆的话只需要把前n/2的数down下来就ok 复杂度是小于O(n) 的 ...
- zcmu 1603 卡斯丁狗的战舰帝国(并查集+模拟)
思路:看到题目我只知道,普通的暴力模拟是不行的,但是不知道用什么办法优化,然后看到网上的大佬们用了并查集恍然大悟: 用并查集维护每条船攻击后的根节点,最后输出查询位置的根节点就行,如果在期间存在该位置 ...
- 【洛谷P4997】不围棋【并查集】【模拟】
题目大意: 题目链接:https://www.luogu.org/problemnew/show/P4997 「不围棋」是一种非常有趣的棋类游戏. 大家都知道,围棋的「气」是指一个棋子所在的联通块相邻 ...
最新文章
- 【管理心得之一】不要用“可有可无”的事,挑战他人对这件事的原则和底线...
- 【PC工具】传说中最好的编程手册管理软件Zeal,支持194种编程文档,学习编程语法查阅必备工具...
- spring boot 框架搭建
- nn.LayerNorm的参数
- 可调稳压电源lm317实验报告_LM317可调直流稳压电源DIY,非常实用!
- log算子 和dog 算子
- 未能成功加载扩展程序_JVM类加载 - 大碗炸酱面
- 【转载】白素贞的身世之谜
- python求两个向量的夹角
- nar神经网络_基于神经网络的预测模型
- sin_cos_tan_cot_sec_cosec 三角函数计算器
- JBoss、Geronimo及Tomcat比较分析
- 云服务器怎么连,云主机连接操作步骤是怎样的?
- 产品冷思考:大而全or小而美如何选择?
- 爱情没有了,生活仍在继续
- 微信小程序源码案例大全
- 为什么特斯拉Q2业绩能超预期?
- 新的放假规定,大年三十还得朝九晚五!
- #五、江恩的共振点是什么?
- 栅格地图建立-Grid-Mapping