给定 \(n\) 个点和 \(m\) 条边,起点 \(s\) ,每个点有颜色。给定多组 \([l,r]\) ,求最大走 \(l...r\) 边权所有可以走到的不同颜色数之和。(同一种颜色在不同区间内算多组)。 \(n,m\leq 5\times 10^5,q\leq 10^5,type\leq 600\) 。
将原图转换成最小生成树是等效的,因为最大值最小的瓶颈边一定在最小生成树上。于是可以从起点进行 \(DFS\) ,求出到每个点的边权最大,然后存到 \(typ\) 数组中表示同一类型的最优点。最后每次查询答案都直接 \(O(600)\) 暴力得出解。
ll ecnt=1,typ[500005];
piii e[500005];
ll ans[1005],anss;
ll maxn[500005],fa[500005];
ll find(ll x){
return (fa[x]==x)?x:fa[x]=find(fa[x]);
}
struct edge{
ll to,nxt,w;
}ee[1000005];
ll head[500005];
void adde(ll u,ll v,ll w){
ee[++ecnt].nxt=head[u];
ee[ecnt].to=v;
ee[ecnt].w=w;
head[u]=ecnt;
}
void dfs(ll x,ll fa){
for(int i=head[x];i;i=ee[i].nxt){
int y=ee[i].to;
if(y==fa)
continue;
maxn[y]=std::max(maxn[x],ee[i].w);
ans[typ[y]]=std::min(maxn[y],ans[typ[y]]);
dfs(y,x);
}
}
ll n,m,q,x,op,M,las,same=1;
int main(){
n=in(),m=in(),q=in(),x=in(),op=in();
if(op==1)
M=in();
FOR(i,1,n){
typ[i]=in();
fa[i]=i;
}
FOR(i,1,600)
ans[i]=10000000000;
FOR(i,1,m){
ll u=in(),v=in(),w=in();
e[i]=mp(w,mp(u,v));
}
sort(e+1,e+m+1);
FOR(i,1,m){
if(find(e[i].sf)!=find(e[i].ss)){
fa[find(e[i].sf)]=find(e[i].ss);
adde(e[i].sf,e[i].ss,e[i].first);
adde(e[i].ss,e[i].sf,e[i].first);
}
}
ans[typ[x]]=0;
dfs(x,x);
FOR(i,1,q){
anss=0;
ll l=in(),r=in();
if(op==1){
l=(l^las)%M+1;
r=(r^las)%M+1;
}
if(l>r)
std::swap(l,r);
FOR(j,1,600){
if(ans[j]<=r){
anss+=std::min(r-ans[j]+1,r-l+1);
}
}
las=anss;
printf("%lld\n",anss);
}
return 0;
}
标签:半仙,ee,ll,C20220712T2,fa,ans,妹子,typ,find
From: https://www.cnblogs.com/zhouzizhe/p/16639827.html