[AGC002D] Stamp Rally (并查集+整体二分)
Description
给你一个n个点m个条边构成的简单无向连通图,有Q组询问,每次询问从两个点x,y走出两条路径,使这两条路径覆盖z个点,求得一种方案使得路径上经过的变的最大编号最小。
Input
第一行两个整数n,m,如题目所述
接下来m行,每行两个整数x,y描述一条边
接下来一个整数Q,如题目所述
接下来Q行,每行三个整数x,y,z,如题目描述
Output
Q行,每行一个正整数,如题目描述
题解:
先想一想,可以用并查集解决,但 \(n^2\) 太慢了,于是就想到了整体二分。
我先是用了一个普通的并查集,结果发现每次都要初始化一遍,T 飞了。
后来想着可以支持删除,就不能路径压缩了(还是T飞),我了解到了一个黑科技,按秩合并。
我们合并两棵树的时候,我们把树高小的挂在树高大的下面,这样就能把树高控制在log级别。
然后我们加边的时候,用栈记录合并的两个节点,分完之后,再从栈中一个个地取出来恢复原样就好了。
到最后一个点的时候我们再把这条边连上,成功AC。
对了,我之前加了这个剪枝:
if(x<y)return;
就是说如果区间里没有数就不往下了,但这会导致有些边没有连,就WA了。
CODE:
#include<iostream>
#include<stack>
#include<cstdio>
using namespace std;
int n,m,q,ans[100005];
int siz[100005],fa[100005];
struct Edge{
int x,y;
}e[100005];
struct Question{
int x,y,z,id;
}Q[100005],tmp[100005];
stack<Edge> s;
int find(int x){
if(x==fa[x])return x;
return find(fa[x]);
}
void solve(int l,int r,int x,int y){
if(l==r){
for(int i=x;i<=y;i++)ans[Q[i].id]=l;
int fx=find(e[l].x),fy=find(e[l].y);
if(siz[fx]>siz[fy])swap(fx,fy);
if(fx!=fy)fa[fx]=fy,siz[fy]+=siz[fx];
return;
}
int mid=l+r>>1;
for(int i=l;i<=mid;i++){
int fx=find(e[i].x),fy=find(e[i].y);
if(siz[fx]>siz[fy])swap(fx,fy);
if(fx!=fy){
fa[fx]=fy,siz[fy]+=siz[fx];
s.push((Edge){fx,fy});
}
}
int tot1=x-1,tot2=0;
for(int i=x,size;i<=y;i++){
int fx=find(Q[i].x),fy=find(Q[i].y);
if(fx==fy)size=siz[fx];
else size=siz[fx]+siz[fy];
if(size>=Q[i].z)Q[++tot1]=Q[i];
else tmp[++tot2]=Q[i];
}
for(int i=1;i<=tot2;i++)Q[tot1+i]=tmp[i];
while(!s.empty()){
Edge e=s.top();s.pop();
fa[e.x]=e.x,siz[e.y]-=siz[e.x];
}
solve(l,mid,x,tot1);
solve(mid+1,r,tot1+1,y);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d",&e[i].x,&e[i].y);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=n;i++)siz[i]=1;
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d%d%d",&Q[i].x,&Q[i].y,&Q[i].z);
Q[i].id=i;
}
solve(1,m,1,q);
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
}
[AGC002D] Stamp Rally (并查集+整体二分)的更多相关文章
- [agc002D]Stamp Rally-[并查集+整体二分]
Description 题目大意:给你一个n个点m个条边构成的简单无向连通图,有Q组询问,每次询问从两个点x,y走出两条路径,使这两条路径覆盖z个点,求得一种方案使得路径上经过的边的最大编号最小.n, ...
- [AGC002D] Stamp Rally
确实有想到重构树,不过没有继续下去的思路. 可能是对重构树的性质不太懂. 这种题目我们可以二分答案,考虑怎么\(check\)呢,整体二分+并查集,建出重构树,找去第一个小于这个数的方点,查询他的子树 ...
- [AGC002D] Stamp Rally 整体二分+并查集
Description 给你一个n个点m个条边构成的简单无向连通图,有Q组询问,每次询问从两个点x,y走出两条路径,使这两条路径覆盖z个点,求得一种方案使得路径上经过的变的最大编号最小. Input ...
- 【做题】agc002D - Stamp Rally——整体二分的技巧
题意:给出一个无向连通图,有\(n\)个顶点,\(m\)条边.有\(q\)次询问,每次给出\(x,y,z\),最小化从\(x\)和\(y\)开始,总计访问\(z\)个顶点(一个顶点只计算一次),经过的 ...
- NOIP2010关押罪犯[并查集|二分答案+二分图染色 | 种类并查集]
题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示 ...
- POJ3228 并查集或二分最大流枚举答案
忘记写题意了.这题题意:给出每个地点的金矿与金库的数量,再给出边的长度.求取最大可通过边长的最小权值使每个金矿都能运输到金库里. 这题和之前做的两道二分枚举最大流答案的问法很相识,但是这里用最大流速度 ...
- 【2018百度之星初赛 B】1001并查集 1004二分 1006不等式
1001 degree 题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6380 并查集向图中加点,分别记录与初始度数最多的点 直接相连的点数.独立的点数 ...
- HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流
二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...
- NOIP 2010 关押罪犯 并查集 二分+二分图染色
题目描述: S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值" ...
随机推荐
- Xcode Warning: “no rule to process file
警告⚠️: warning: no rule to process file '/Users/Kingdev/Desktop/Git/finance_iOS/finance/Library/MBpro ...
- 微信小程序text标签
最近在做小程序,使用<text>标签的时候发现里面的文本text-family不生效, 经过试验,发现直接在text标签的class设置不生效,可以在外层包一个父元素就可以设置了. < ...
- tcl之关于TCL
- 利用PHPExcel 实现excel数据的导入导出(源码实现)
利用PHPExcel 实现excel数据的导入导出(源码实现) 在开发过程中,经常会遇到导入导出的需求,利用phpexcel类实现起来也是比较容易的,下面,我们一步一步实现 提前将phpexcel类下 ...
- python网络-多任务实现之协程(27)
一.协程 协程,又称微线程,纤程.英文名Coroutine. 协程不是进程,也不是线程,它就是一个函数,一个特殊的函数——可以在某个地方挂起,并且可以重新在挂起处继续运行.所以说,协程与进程.线程相比 ...
- 用python给图片添加半透明水印
# coding:utf-8 from PIL import Image, ImageDraw, ImageFont def add_text_to_image(image, text): font ...
- Broken robot CodeForces - 24D (概率DP)
You received as a gift a very clever robot walking on a rectangular board. Unfortunately, you unders ...
- HihoCoder - 1636 Pangu and Stones(区间DP)
有n堆石子,每次你可以把相邻的最少L堆,最多R堆合并成一堆. 问把所有石子合并成一堆石子的最少花费是多少. 如果不能合并,输出0. 石子合并的变种问题. 用dp[l][r][k]表示将 l 到 r 之 ...
- [USACO]Bovine Genomics
Description 给定两个字符串集合A,B,均包含N个字符串,长度均为M,求一个最短的区间[l,r],使得不存在字符串\(a\in A,b\in B,\)且\(a[l,r]=b[l,r]\) , ...
- poj 3258 跳房子问题 最大化最小值
题意:奶牛跳房子,从n块石头中移除M块,使得间距最小的最大值?思路:“转换” 从N块中选择n-m块使得两两之间的间距尽可能大 c(d) 是间距最大的满足条件,即第一块 放在 xi的位置 下一块就要放在 ...