点击打开链接
首先给出 2 个结论:
考虑建出一棵 MST
对于每个结点维护一棵线段树,在儿子的颜色信息上维护最小距离
同时在叶节点处用 m u l t i s e t multiset multiset 维护当前颜色的所有距离即可
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
#include
using namespace std;
const int N(200100),inf(0x3f3f3f3f);
struct LINES{
int x,y,z;
}lines[N];
int n,m,k,q,fa[N],col[N],FA[N],W[N],mndis[N];
int e[N<<1],w[N<<1],ne[N<<1],h[N],idx;
int tot,root[N],seg[N*38],lc[N*38],rc[N*38];
int tot2,dy[N*38];
bool leaf[N];
multiset<int> se[N<<1],ans;
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
bool cmp(const LINES &x,const LINES &y){ return x.z<y.z;}
int get_father(int x){ return x==fa[x]?x:fa[x]=get_father(fa[x]);}
int insert(int p,int l,int r,int pos,int c){
if(!p) p=++idx;
if(l==r){
if(!dy[p]) dy[p]=++tot2;
se[dy[p]].insert(c);seg[p]=min(seg[p],c);
return p;
}
int mid=(l+r)>>1;
if(mid>=pos) lc[p]=insert(lc[p],l,mid,pos,c);
else rc[p]=insert(rc[p],mid+1,r,pos,c);
seg[p]=min(seg[lc[p]],seg[rc[p]]);
return p;
}
void dfs(int u,int fa){
leaf[u]=1,FA[u]=fa;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(v!=fa) leaf[u]=0,dfs(v,u),W[v]=w[i],root[u]=insert(root[u],1,n,col[v],w[i]);
}
}
int query(int p,int l,int r,int L,int R){
if(L>R||!p) return inf;
if(L<=l&&r<=R) return seg[p];
int mid=(l+r)>>1;
if(mid>=L&&mid<R) return min(query(lc[p],l,mid,L,R),query(rc[p],mid+1,r,L,R));
if(mid>=L) return query(lc[p],l,mid,L,R);
return query(rc[p],mid+1,r,L,R);
}
void cover(int p,int l,int r,int pos,int w){
if(l==r){
se[dy[p]].erase(se[dy[p]].find(w));
if(se[dy[p]].empty()) seg[p]=inf;
else seg[p]=*se[dy[p]].begin();
return;
}
int mid=(l+r)>>1;
if(mid>=pos) cover(lc[p],l,mid,pos,w);
else cover(rc[p],mid+1,r,pos,w);
seg[p]=min(seg[lc[p]],seg[rc[p]]);
}
void add(int a,int b,int c){ e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;}
int main(){
n=read(),m=read(),k=read(),q=read();
for(int i=1,x,y,z;i<=m;i++) x=read(),y=read(),z=read(),lines[i]={x,y,z};
sort(lines+1,lines+m+1,cmp);
for(int i=1;i<=n;i++) fa[i]=i;
memset(h,-1,sizeof(h));
for(int i=1,j=0;i<=m;i++){
if(j==n-1) break;
int fa0=get_father(lines[i].x),fa1=get_father(lines[i].y);
if(fa0!=fa1){
fa[fa0]=fa1,j++;
add(lines[i].x,lines[i].y,lines[i].z),add(lines[i].y,lines[i].x,lines[i].z);
}
}
memset(seg,0x3f,sizeof(seg));
for(int i=1;i<=n;i++) col[i]=read();
dfs(1,-1);
for(int i=1;i<=n;i++) if(!leaf[i]) mndis[i]=min(query(root[i],1,n,1,col[i]-1),query(root[i],1,n,col[i]+1,n)),ans.insert(mndis[i]);
while(q--){
int x=read(),val=read();
if(!leaf[x]){
ans.erase(ans.find(mndis[x]));
mndis[x]=min(query(root[x],1,n,1,val-1),query(root[x],1,n,val+1,n));
ans.insert(mndis[x]);
}
if(x!=1){
ans.erase(ans.find(mndis[FA[x]]));
cover(root[FA[x]],1,n,col[x],W[x]);
insert(root[FA[x]],1,n,val,W[x]);
mndis[FA[x]]=min(query(root[FA[x]],1,n,1,col[FA[x]]-1),query(root[FA[x]],1,n,col[FA[x]]+1,n));
ans.insert(mndis[FA[x]]);
}
col[x]=val;
printf("%d\n",*ans.begin());
}
return 0;
}