2020牛客NOIP赛前集训营-提高组B-牛半仙的妹子图(Kruskal)

博客内容涉及2020年牛客NOIP赛前集训营提高组B题的解题思路,主要使用Kruskal算法解决[l,r]区间颜色数之和问题。通过Kruskal找到最小生成树,记录各颜色的最大边权,从而优化复杂度达到约O(n^2)。博主在后记中提到,实际正解应为O(NlogQ),即求每个点到x的最长边并离散化,进行二分查询,但博主未能实现此方法。" 62889542,5735064,Unity3D登录界面实现:GUI vs GUILayout,"['Unity3D', '游戏开发', 'GUI', 'GUILayout']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Statement

在这里插入图片描述

Solution

  • 题目其实是求[l,r][l,r][l,r]内颜色数之和
  • 我们看到ci≤600c_i \leq600ci600
  • 快乐~
  • 于是考虑每一种颜色,可以做到6∗1076*10^76107时复,约等于O(nn)O(n\sqrt n)O(nn)
  • 先用KruskalKruskalKruskal跑出MSTMSTMST
  • 然后记录到达每一种颜色路径上最大边权(#困难接受程度)
  • 那么就可以算r−max⁡(l,ti)+1r-\max(l,t_i)+1rmax(l,ti)+1次答案
  • 代码很好写
#include <bits/stdc++.h>
#define ll long long
const int N=5e5+10;
using namespace std;
int n,m,q,X,C,op,h[N],tot,f[N],c[N],M;
int t[N];//the minimum cost to gain access to col[i]
struct rd{int u,v,w;}s[N<<1];
struct Edge{int v,nxt,w;}e[N<<1];
void add(int u,int v,int w)
{e[++tot].v=v,e[tot].nxt=h[u],e[tot].w=w,h[u]=tot;}
bool cmp(rd a,rd b){return a.w<b.w;}
int sf(int x){return x==f[x]?x:f[x]=sf(f[x]);}
void dfs(int x,int fx,int mn)
{
	t[c[x]]=min(t[c[x]],mn);
	for(int i=h[x];i;i=e[i].nxt)
	{
		int v=e[i].v;
		if(v==fx) continue;
		dfs(v,x,max(mn,e[i].w));
	}
}
int main()
{
	scanf("%d%d%d%d%d",&n,&m,&q,&X,&op);
	if(op) scanf("%d",&M);
	for(int i=1;i<=n;i++) scanf("%d",c+i),C=c[i]>C?c[i]:C,f[i]=i;
	for(int i=1;i<=C;i++) t[i]=1<<30;
	for(int i=1;i<=m;i++) scanf("%d%d%d",&s[i].u,&s[i].v,&s[i].w);
	sort(s+1,s+m+1,cmp);
	for(int i=1;i<=m;i++)
	{
		int x=s[i].u,y=s[i].v,z=s[i].w;
		if(sf(x)^sf(y)) f[f[x]]=f[y],add(x,y,z),add(y,x,z);
	}
	dfs(X,0,0);
	ll ans=0;
	for(int i=1,l,r;i<=q;i++)
	{
		scanf("%d%d",&l,&r);
		if(op) l=(l^ans)%M+1,r=(r^ans)%M+1;
		if(l>r) l^=r^=l^=r;
		ll tmp=0;
		for(int i=1;i<=C;i++)
			if(t[i]<=r) tmp+=1ll*(r-max(l,t[i])+1);
		printf("%lld\n",ans=tmp);	
	}
}

Postscript

  • 考场上没看懂题面
  • 其实正解应该是O(NlogQ)O(NlogQ)O(NlogQ)的,求出每个点到x的最长的边的长度并保存,离散化,最后每次O(logQ)O(logQ)O(logQ)二分查询
  • 可惜我太蒻了不会写,欢迎大佬在评论区指出!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值