Switch Grass P
题解
由于答案一定是某一条边的边权,而两点只有当颜色相同时才会被忽略掉,所以可以发现这条边一定是在该图的最小生成树上。
于是我们可以先将这棵树给建出来,考虑每个点与他儿子连边的贡献。
我们可以先给每个点所有儿子的颜色开一个multiset,记其为,存储它和所有颜色为
的儿子的边长,而每条边只会被装进去一次,总共
条边,空间不会炸,再用一个multiset存储每个点的
。
我们可以再用一棵线段树维护每个节点与其儿子的最近异色点对的连接边长。
所以对于一个节点,它的答案只会是前两者的大小,修改查询等操作都很容易维护。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200005
typedef long long LL;
const int INF=0x3f3f3f3f;
typedef pair<int,int> pii;
typedef map<int,multiset<int> >::iterator MSIT;
typedef set<pii>::iterator SPIT;
#define gc() getchar()
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
int n,m,k,q,tot,head[MAXN];
struct edge{int to,nxt,paid;}e[MAXN<<1];
void addEdge(int u,int v,int w){e[++tot]=(edge){v,head[u],w};head[u]=tot;}
namespace MST{
struct edge1{
int u,v,w;
bool friend operator < (const edge1 &a,const edge1 &b){
return a.w<b.w;
}
}G[MAXN];
int fa[MAXN];
void makeSet(int x){for(int i=1;i<=x;i++)fa[i]=i;}
int findSet(int x){return fa[x]==x?x:fa[x]=findSet(fa[x]);}
void GMST(){
makeSet(n);sort(G+1,G+m+1);int cnt=0;
for(int i=1;i<=m;i++){
int u=G[i].u,v=G[i].v;
int fu=findSet(u),fv=findSet(v);
if(fu==fv)continue;cnt++;fa[fu]=fv;
addEdge(u,v,G[i].w);addEdge(v,u,G[i].w);
}
}
}
using namespace MST;
struct Segment_Tree{
int tr[MAXN<<2];
void pushup(int rt){tr[rt]=min(tr[rt<<1],tr[rt<<1|1]);}
void build(int rt,int l,int r){
if(l==r)return (void)(tr[rt]=INF);
int mid=l+r>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void update(int rt,int l,int r,int ai,int aw){
if(l==r)return (void)(tr[rt]=aw);
int mid=l+r>>1;
if(ai<=mid)update(rt<<1,l,mid,ai,aw);
else update(rt<<1|1,mid+1,r,ai,aw);
pushup(rt);
}
}Tree;
multiset<pii>bst[MAXN];
map<int,multiset<int> >cls[MAXN];
int cl[MAXN],f[MAXN],ww[MAXN];
void dfs(int u,int father){
f[u]=father;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;if(v==father)continue;
ww[v]=e[i].paid;cls[u][cl[v]].insert(ww[v]);
dfs(v,u);
}
for(MSIT it=cls[u].begin();it!=cls[u].end();it++)
bst[u].insert(make_pair(*(*it).second.begin(),(*it).first));
if(!bst[u].empty()){
SPIT it=bst[u].begin();
if(cl[u]!=(*it).second)Tree.update(1,1,n,u,(*it).first);
else{
it++;
if(it==bst[u].end())Tree.update(1,1,n,u,INF);
else Tree.update(1,1,n,u,(*it).first);
}
}
}
signed main(){
scanf("%d %d %d %d",&n,&m,&k,&q);
for(int i=1;i<=m;i++){
int u,v,w;read(u);read(v);read(w);
G[i]=(edge1){u,v,w};
}
GMST();
for(int i=1;i<=n;i++)read(cl[i]);
Tree.build(1,1,n);dfs(1,0);
while(q--){
int u,c2;read(u);read(c2);
if(f[u]){
int c1=cl[u];
bst[f[u]].erase(bst[f[u]].find(make_pair(*cls[f[u]][c1].begin(),c1)));
cls[f[u]][c1].erase(cls[f[u]][c1].find(ww[u]));
if(cls[f[u]][c1].empty())cls[f[u]][c1].insert(INF);
bst[f[u]].insert(make_pair(*cls[f[u]][c1].begin(),c1));
if(!cls[f[u]][c2].empty())
bst[f[u]].erase(bst[f[u]].find(make_pair(*cls[f[u]][c2].begin(),c2)));
cls[f[u]][c2].insert(ww[u]);
bst[f[u]].insert(make_pair(*cls[f[u]][c2].begin(),c2));
SPIT it=bst[f[u]].begin();
if(cl[f[u]]!=(*it).second)Tree.update(1,1,n,f[u],(*it).first);
else{
it++;
if(it==bst[f[u]].end())Tree.update(1,1,n,f[u],INF);
else Tree.update(1,1,n,f[u],(*it).first);
}
}
if(!bst[u].empty()){
SPIT it=bst[u].begin();
if(c2!=(*it).second)Tree.update(1,1,n,u,(*it).first);
else{
it++;
if(it==bst[u].end())Tree.update(1,1,n,u,INF);
else Tree.update(1,1,n,u,(*it).first);
}
}
cl[u]=c2;printf("%d\n",Tree.tr[1]);
}
return 0;
}
谢谢!!!