题解:AT_abc040_d [ABC040D] 道路の老朽化対策について
一道很经典的并查集离线题。
Solution
Idea
我们发现每一次都对于一个询问单独加边,时间复杂度肯定会爆炸。
于是我们思考:如何才能让加边的次数变少呢?
不难发现,我们的每一条边都有一个修建年份,并且修建在
如果我们对于询问按照排斥年份从晚到早排序,把边按照修建时间从晚到早排序,则我们先加入的边一定不会被后面的询问排斥,因为显然越靠后的人所能接受的年份越早。
显然有一个要求:对于每一组询问只能添加修建年份更晚的边。如果我们按照排序,每一次更新,我们都只需在原有的基础上添加修建年份在
注意因为排了序,所以要记录询问序号,然后最后统一输出。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=100005,M=200005;
int n,m;
struct node{
int u,v,y;
friend bool operator <(node _,node __){
return _.y>__.y;
}
}a[M];
struct ask{
int x,y,id;
friend bool operator <(ask _,ask __){
return _.y>__.y;
}
}e[N];
int fa[N],siz[N];
int findd(int now){
if(fa[now]==now)return now;
return fa[now]=findd(fa[now]);
}
void vnion(int u,int v){
u=findd(u),v=findd(v);
if(u==v)return;
fa[u]=v;
siz[v]+=siz[u];
}
int q,ans[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
fa[i]=i;
siz[i]=1;
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].y);
}
sort(a+1,a+m+1);
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d%d",&e[i].x,&e[i].y);
e[i].id=i;
}
sort(e+1,e+q+1);
for(int i=1,j=1;i<=q;i++){
while(j<=m&&a[j].y>e[i].y){
vnion(a[j].u,a[j].v);
j++;
}
ans[e[i].id]=siz[findd(e[i].x)];
}
for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】