题目链接
题目思路
查询和修改都离线操作
然后查询使用优先队列进行启发式合并即可
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int m,n,q;
ll a[maxn];
ll pr[maxn];
int fa[maxn];
int findd(int x){
return x==fa[x]?x:fa[x]=findd(fa[x]);
}
struct edge{
int u,v,w;
}e[maxn];
bool cmp(edge a,edge b){
return a.w<b.w;
}
struct node{
int k,id;
friend bool operator<(node a,node b){
return a.k>b.k;
}
};
priority_queue<node> pq[maxn];
signed main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
fa[i]=i;
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
sort(e+1,e+1+m,cmp);
for(int i=1,x,k;i<=q;i++){
scanf("%d%d",&x,&k);
pq[x].push({k,i});
}
for(int i=1;i<=m;i++){
int u=findd(e[i].u);
int v=findd(e[i].v);
if(u==v) continue;
while(!pq[u].empty()&&pq[u].top().k+a[u]<e[i].w){
pr[pq[u].top().id]=pq[u].top().k+a[u];
pq[u].pop();
}
while(!pq[v].empty()&&pq[v].top().k+a[v]<e[i].w){
pr[pq[v].top().id]=pq[v].top().k+a[v];
pq[v].pop();
}
if(pq[u].size()<pq[v].size()) swap(u,v);
// v去合并u
while(pq[v].size()){
pq[u].push(pq[v].top());
pq[v].pop();
}
a[u]+=a[v];
fa[v]=u;
}
for(int i=1;i<=n;i++){
while(!pq[i].empty()){
pr[pq[i].top().id]=pq[i].top().k+a[i];
pq[i].pop();
}
}
for(int i=1;i<=q;i++){
printf("%lld\n",pr[i]);
}
return 0;
}