首页 > 其他分享 >2024/10/8

2024/10/8

时间:2024-10-08 23:44:26浏览次数:8  
标签:10 val int auto top 最小 2024 FindSet

给定一张图,每个点有一个颜色。每次操作求改一个颜色,然后询问所有不同颜色点对的最短距离。


给出一种 \(O(n\sqrt{n})\) 的做法。

先按照边权从小到大排序,然后将边分块。

对于每一个块,我们只需要快速判断块内是否存在一条边的两点颜色不同即可。

对于一个块可以算出 \(\sum (col_{u_i}-col_{v_i})\times rnd_i\),其中 \(rnd_i\) 是随机赋权的常数。当这个值不为 \(0\) 时就当前块内就存在一条满足条件的边。

每次修改和查询均为 \(O(\sqrt{n})\)。

[THUPC2022 初赛] 最小公倍树

我们知道一条边的权值为 \(\frac{uv}{\gcd(u,v)}\)。

考虑枚举两个点的公因子 \(k\)。可以发现,对于一个 \(k\),在区间 \([L,R]\) 中的所有满足条件的点 \(dk,(d+1)k,(d+2)k,\dots\),我们直接将它们向 \(dk\) 连边是最优的。

所以总边数是 \(O(n\log n)\) 的,然后跑一边最小生成树即可。

CF1120D Power Tree

我们将叶子节点按照 dfs 序排出来,那么一个节点能够控制的叶子节点必然是一个区间,记为\([l_x,r_x]\)。

控制一个点就相当于将一个区间增加。我们来考虑差分,相当于将 \(a_{l_x}\) 加,将 \(a_{r_x+1}\) 减。

所以我们能够修改 \(a_1\) 到 \(a_{n+1}\) 的值。对于每一个区间,我们可以选择连接一条边 \(l_x\to r_x+1\),目标是让所有点都与 \(n+1\) 连通。

跑一边最小生成树即可。注意要记录所有可行的方案。

HNOI2010 城市建设

动态最小生成树。用线段树分治解决。

让我们考虑不在操作区间 \([l,r]\) 中所有边:

  • 将区间 \([l,r]\) 中的边设为 \(inf\),跑一边最小生成树后不在区间 \([l,r]\) 内且不在最小生成树上的边最后一定不会在最小生成树上。

  • 将区间 \([l,r]\) 中的边设为 \(-inf\),跑一边最小生成树后不在区间 \([l,r]\) 内且在最小生成树上的边最后一定会在最小生成树上。

最后分治到 \(l=r\) 时,只需要把剩下的边再跑一边最小生成树就可以求出第 \(l\) 个询问的答案。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e4 + 5, inf = 0x3f3f3f3f3f3f3f3f;
int n, m, q, fa[N], siz[N], flg[N], top;
int u[N], v[N], w[N], val[N], a[N], b[N];
vector<int> vec[N << 2];
int FindSet(int x) {return fa[x] == x ? x : FindSet(fa[x]);}
void insert(int p, int l, int r, int x, int y) {
	int mid = l + r >> 1;
	vec[p].push_back(y);
	if(l == r) return;
	if(x <= mid) insert(p << 1, l, mid, x, y);
	else insert(p << 1 | 1, mid + 1, r, x, y);
}
struct node {int x, y;} stk[N];
void del(int p) {while(top > p) fa[stk[top].x] = stk[top].x, siz[stk[top].y] -= siz[stk[top].x], top--;}
void merge(int u, int v) {
	if(siz[u] > siz[v]) swap(u, v);
	stk[++top] = node({u, v}), fa[u] = v, siz[v] += siz[u];
}
void solve(int p, int l, int r, int ans, vector<int> g) {
 	int mid = l + r >> 1, now = top;
	vector<int> vc;
	if(l == r) {
		val[a[l]] = w[a[l]] = b[l];
		sort(g.begin(), g.end(), [](int i, int j) {return val[i] < val[j];});
		for(auto x : g) {
			int u = FindSet(::u[x]), v = FindSet(::v[x]);
			if(u == v) continue;
			merge(u, v); ans += val[x];
		}
		return printf("%lld\n", ans), del(now), void();
	}
	for(auto x : g) val[x] = w[x], flg[x] = 2; for(auto x : vec[p]) val[x] = inf;
	sort(g.begin(), g.end(), [](int i, int j) {return val[i] < val[j];});
	for(auto x : g) {
		int u = FindSet(::u[x]), v = FindSet(::v[x]);
		if(u == v) {if(val[x] != inf) flg[x] = 0; continue;}
		merge(u, v);
	} del(now);
	for(auto x : vec[p]) val[x] = -inf;
	sort(g.begin(), g.end(), [](int i, int j) {return val[i] < val[j];});
	for(auto x : g) {
		int u = FindSet(::u[x]), v = FindSet(::v[x]);
		if(u == v) continue;
		if(val[x] != -inf) flg[x] = 1; merge(u, v);
	} del(now);
	for(auto x : g) val[x] = w[x];
	for(auto x : g) if(flg[x] == 1) {
		int u = FindSet(::u[x]), v = FindSet(::v[x]);
		if(u != v) merge(u, v), ans += w[x];
	} else if(flg[x] == 2) vc.push_back(x);
	solve(p << 1, l, mid, ans, vc), solve(p << 1 | 1, mid + 1, r, ans, vc), del(now);
}
signed main() {
	scanf("%lld %lld %lld", &n, &m, &q);
	for(int i = 1; i <= n; i++) fa[i] = i, siz[i] = 1;
	for(int i = 1; i <= m; i++) scanf("%lld %lld %lld", &u[i], &v[i], &w[i]), val[i] = w[i];
	for(int i = 1; i <= q; i++) scanf("%lld %lld", &a[i], &b[i]), insert(1, 1, q, i, a[i]);
	vector<int> g; for(int i = 1; i <= m; i++) g.push_back(i);
	solve(1, 1, q, 0, g);
	return 0;
}

UOJ176 新年的繁荣

首先发现若存在两个点它们的权值相同,将它们之间连上边肯定是优的。

考虑剩下权值互不相同的点。容易发现权值很小,于是考虑枚举权值,记为 \(i\)。

每次需要找到 \(x\ and\ y=i\) 且 \(x,y\) 不在一个连通块中的点,并将它们连上边。

但这样时间复杂度不对。可以考虑将 \(x\) 下放到 \(x\) 的子集中,就只需要枚举 \(i\ or\ 2^j\) 即可。

APIO2008 免费道路

sol1

将第 \(i\) 条边附上权值 \(i\),然后跑一边与 P2619 Tree I 相同的二分即可。

sol2

我们可以先找出所有必须被选择的鹅卵石路,可以通过一次最小生成树来解决。

然后将这些鹅卵石路强制选上,之后再优先选鹅卵石路直到选了 \(k\) 条,也可以通过一次最小生成树来解决。

AGC037D Sorting a Grid

若能够使 \(C\) 变成 \(D\),那么 \(C\) 需要满足 \(C\) 的每一行上的数与 \(D\) 的对应行上的数重排后相同。

若能够使 \(B\) 变成 \(C\),那么 \(B\) 需要满足 \(B\) 的每一列上在 \(D\) 中的行(颜色)互不相同。

让我们依次枚举每一列,我们可以将 \(A\) 的一行开一个点,将每种颜色开一个点,然后将行与上面有的颜色连一条边,然后跑一边二分图匹配。

每次找到的一个完美匹配就可以确定 \(B\) 的一列。

容易从 \(B\) 变到 \(C\)。

BZOJ4808 马

按照马移动的方式连边,然后跑一边最大匹配来求最大独立集。

标签:10,val,int,auto,top,最小,2024,FindSet
From: https://www.cnblogs.com/ddxrS/p/18453289

相关文章

  • 10.8
    以下代码的输出结果是什么?intX=100;intY=200;System.out.println("X+Y="+X+Y);System.out.println(X+Y+"=X+Y");为什么会有这样的输出结果?第一条输出结果是:X+Y=100200第二条输出结果是:300=X+Y第一条中“”中输出形式为字符串然后又连接了另一个数字,最终产生了一个字符......
  • ChatGPT4.0国内中文版镜像网站整理【10月持续更新】
    一、什么是镜像网站镜像网站是指将原始网站的内容复制并放置在另一服务器上的网站。这个概念通常应用于提供备用访问途径,为主站点的繁重流量提供缓解。一般来说,镜像网站会更新以保持与原始网站相同的内容,但这个更新的频率可能因镜像站点的设定不同而不同。二、ChatGPT与国内......
  • Hetao P1031 萌萌题 题解 [ 蓝 ] [ 线性 dp ]
    萌萌题:一道结合了观察性质的线性dp。观察我们先考虑极端情况:所有数相同,所有数降序排列两种情况。对于所有数相同的情况,我们发现,最终可以合并出来的区间,最多只有\(n\logn\)个。怎么证明?考虑固定右端点,那么我们想要合并出一个点,就得选\(2^k\)个数出来,这就有\(\logn\)......
  • 20241008_Day 04
    helloworld!1.安装NOTEPAD++2.新建代码文件夹3.新建JAVA文件1.可以新建text文件,修改后缀为.java2.打开方式修改为notepad+++4.编写代码具体为:javapublicclassHello{publicstaticvoidmain(String[]args){System.out.print("Hello,world!");}}5.......
  • 10.8日noip联考总结
    10.8日noip联考总结T1考试的时候没有想到可以快速用组合数进行统计答案,于是在正常的匹配栈里还套了一个\(O(n)\)的统计答案。其实只需要在里面统计个数,在用乘法原理就可以了。括号匹配引导我们使用匹配栈,而需要快速统计答案又可以想到组合计数。T2这题不用输出方案的话就......
  • 【电商搜索】现代工业级电商搜索技术-EMNLP2024-无监督的用户偏好学习
    【电商搜索】现代工业级电商搜索技术-EMNLP2024-无监督的用户偏好学习0.论文信息Title:UnsupervisedHumanPreferenceLearningAuthors:SumukShashidhar,AbhinavChinta,VaibhavSahai,DilekHakkaniTurComments:EMNLP2024MainConferencehttps://arxiv.or......
  • 2018_10_28_01
    动态替换图片最简单的示例<divclass="img-wrapper"><divonclick='replacement'><imgsrc='[图片1]'></div><!-----------------><!--忽略同类型代码.--><!----------------->......
  • 【C++ 10】多态
    文章目录......
  • 笑傲江湖单机版安装教程+虚拟机一键端+GM+10职业单人副本
    今天给大家带来一款单机游戏的架设:笑傲江湖10职业单机版单人副本坐骑门徒新时装商完整任务。另外:本人承接各种游戏架设(单机+联网)本人为了学习和研究软件内含的设计思想和原理,带了架设教程仅供娱乐。教程是本人亲自搭建成功的,绝对是完整可运行的,踩过的坑都给你们填上了。如果你......
  • NewStar2024-week1
    前言:刚开始比赛,时间比较多尝试了一下所有题目,难度也很友好,之后就写密码了,写全部太累了Week1CryptoBase4C4A575851324332474E324547554B494A5A4446513653434E564D444154545A4B354D45454D434E4959345536544B474D5134513D3D3D3D秒了一眼秒了p,q相近或者factordb查"""fro......