首页 > 其他分享 >CEOI2023D1T3(LOJ4019) Brought Down the Grading Server? (分治+欧拉回路)

CEOI2023D1T3(LOJ4019) Brought Down the Grading Server? (分治+欧拉回路)

时间:2024-01-22 18:55:52浏览次数:29  
标签:CEOI2023D1T3 Grading int 出度 入度 Down MAXN 回路 欧拉

因为我们有 \(S=2^k\),所以我们先考虑 \(k=1\) 即 \(S=2\) 的时候应该怎么做。

发现如果我们对于每一个核心从 \(t_1\) 向 \(t_2\) 连一条无向边,如果我们把 「不交换 \(t_1,t_2\)」 看成将这条边定向为 \(t_1\to t_2\),否则如果「交换 \(t_1,t_2\)」看成将这条边定向为 \(t_2\to t_1\),我们会发现对于一个数 \(x\) 在左边出现的次数相当于 \(x\) 的出度,\(x\) 在右边出现的次数相当于 \(x\) 的入度,我们要找到一种定向方法使得这个图上每个点的入度和出度相差不超过 \(1\)。

于是我们想到了欧拉回路,欧拉回路上每个点的出度和入度相等(因为每个点出去一次进来一次),但问题是我们的这个无向图不一定有欧拉回路,且我们只需要入度和出度相差不超过 \(1\)。

考虑到一个无向图有欧拉回路当且仅当这个图上的每一个点的度数都为偶数,于是我们想到建立一个源点,从这个源点向每个度数为奇数的点连一条边,然后在这个新的图上跑欧拉回路,最后只用关注那些原先就在这个图上的边,这样就可以保证每个点的出度和入度相差不超过 \(1\) 了。

接下来考虑 \(S>2\) 应该怎么做,由于 \(S=2^k\),我们可以先将前 \(2^{k-1}\) 个评测看成一个整体,将后 \(2^{k-1}\) 个评测看成一个整体,我们要使得对于任意一个数 \(x\),其在前 \(2^{k-1}\) 个中出现的次数与其在后 \(2^{k-1}\) 个评测中出现的次数相等,于是我们发现只需要将 \(t_i\) 与 \(t_{n-i}\) 连边,然后跑一遍欧拉回路,然后分治地处理 \([1,2^{k-1}]\) 与 \([2^{k-1}+1,2^{k}]\) 即可。

因为我们可能会建重边,所以可以在每条边中插入一个点,以记录重边的编号(当然可能不记录也是对的,但是我没验证过)。

时间复杂度 \(O((nS + T)\log S)\)。

const int MAXN = 5e6 + 5;
int ecnt, n, s, t, d[MAXN], hd[MAXN], st[MAXN], top;
vector<vector<int>> a;
struct _node {
	int v, ex, rev;
};
vector<_node> G[MAXN];
bool vis[MAXN];
struct _edge {
	int u, v, i, j;
	bool operator < (const _edge b) const {
		return u == b.u ? v < b.v : u < b.u;
	}
};

void Hierholzer(int x) {
	vis[x] = true;
	for (int &i = hd[x]; i < (int)G[x].size();) {
		if (G[x][i].ex) {
			G[x][i].ex = G[G[x][i].v][G[x][i].rev].ex = 0;
			i++;
			Hierholzer(G[x][i - 1].v);
		} else ++i;
	}
	st[++top] = x;
}

void add(int x, int y) {
	G[x].push_back({y, 1, G[y].size()});
	G[y].push_back({x, 1, G[x].size() - 1});
}

void solve(int l, int r) {
	int len = (r - l + 1);
	ecnt = top = 0;	
	int x = t;
	unordered_map<int, pair<int, int>> emap;
	for (int i = 0; i < len / 2; ++i) {
		for (int j = 1; j <= n; ++j) {
			const int u = a[j][l + i], v = a[j][r - i];
			if (u == v) continue;
			add(u, ++x); add(v, x);
			emap[x] = make_pair(i, j);
			d[u]++; d[v]++; d[x] += 2;
		}
	}
	for (int i = 1; i <= t; ++i) {
		if (d[i] % 2 == 1) {
			add(0, ++x);
			add(i, x);
		}
	}
	for (int i = 0; i <= t; ++i) {
		if (vis[i]) continue;
		top = 0;
		Hierholzer(i);
		reverse(st + 1, st + top + 1);
		for (int j = 3; j <= top; j += 2) {
			if (!st[j] || !st[j - 2] || st[j] == st[j - 2]) continue;
			const auto _ = emap[st[j - 1]];
			int &u = a[_.second][l + _.first], &v = a[_.second][r - _.first];
			if (u != st[j - 2]) {
				swap(u, v);
			}
		}
	}
	for (int i = 0; i <= t + x; ++i) G[i].clear(), vis[i] = false, d[i] = hd[i] = 0;
	if (len != 2) {
		solve(l, mid); solve(mid + 1, r);
	}
}

void work() {
	cin >> n >> s >> t;
	a.resize(n + 1);
	for (int i = 1; i <= n; ++i) {
		a[i].resize(s + 1);
		for (int j = 1; j <= s; ++j)
			cin >> a[i][j];
	}
	solve(1, s);
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= s; ++j) cout << a[i][j] << ' ';
		cout << endl;
	}
}

标签:CEOI2023D1T3,Grading,int,出度,入度,Down,MAXN,回路,欧拉
From: https://www.cnblogs.com/XiaoQuQu/p/17980756

相关文章

  • ubuntu22.04 mysql服务每天自动shutdown问题
    1.问题描述MYSQL每天自动关闭,查看/var/log/mysql/error.log.1.gz,内容如下:2019-06-12T06:33:13.582973+08:000[Note]Shuttingdownplugin‘CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS’2019-06-12T06:33:13.583022+08:000[Note]Shuttingdownplugin‘CONNECTION_CON......
  • Markdown学习
    标题(#+空格+标题名字一级标题(##+空格+标题名字二级标题(###空格+标题名字三级标题字体加粗斜体加粗斜体划线引用好好学习,天天向上分割线图片超链接百度表格姓名性别年龄小赵男12小刘男13代码#include<iostream>usingna......
  • 学会Markdown从这里开始
    关于MarkdownMarkdown是什么?引用Markdown官方教程的一句话就是:Markdown是一种轻量级的标记语言,允许人们使用易读易写的纯文本格式编写文档。Markdown的优点有哪些?使用markdown编辑可以让我们在写作的过程中顺便对文章进行排版,而不用在需要添加格式的时候中断写作;Markdown可......
  • 在Markdown中使用mermaid画图之流程图
    流程图流程图由流程图方向、节点、节点形状、节点间关系构成声明流程图flowchartLR//flowchart声明为流程图、LR确定流程图从左至右的方向 id1[test1]//id--创建出一个节点、括号内为该节点显示的内容 id2[test2] id3[test3]流程图的方向有以下几种选择:TB-从上到......
  • 如何使用Markdown编写笔记
    Markdown是什么?Markdown是一种轻量级标记语言,创始人为约翰·格鲁伯(JohnGruber)。它允许人们使用易读易写的纯文本格式编写文档,然后转换成有效的XHTML(或者HTML)文档。这种语言吸收了很多在电子邮件中已有的纯文本标记的特性。由于Markdown的轻量化、易读易写特性,并且对于图片......
  • MrakDown新手使用
    MarkDown学习二级标题字体hellowordhellowordhellowordhelloword引用千夜学java走向人生巅峰分割线图片超链接[千夜的博客](千夜学java-博客园(cnblogs.com))列表abc132d1addada表格姓名年龄成绩张三18100李四1990王五208......
  • node-sass 安装出错 Cannot download "https://github.com/sass/node-sass...
    Downloadingbinaryfromhttps://github.com/sass/node-sass/releases/download/v4.14.1/win32-x64-83_binding.nodeCannotdownload"https://github.com/sass/node-sass/releases/download/v4.14.1/win32-x64-83_binding.node": github网站大多时候都访问不到,下载 win32-x......
  • convert code 2 markdown
    convertcodemarkdown,collectmarkdown,uncollectmarkdown"""convertcodetomarkdown"""importdatetimeimportosimportreclassCodeToMarkDown:"""_summary_"""__slots__=[&q......
  • 安装nuxt3报错:Error: Failed to download template from registry: fetch failed
    问题复现:输入命令安装nuxt3pnpmdlxnuxi@latestinitnuxt-app然后出现下面错误ERRORError:Failedtodownloadtemplatefromregistry:fetchfailed 解决方案:配置hosts,Mac中路径是/etc/hosts,在下面追加一行185.199.108.133raw.githubusercontent.com下......
  • code2markdown class
    """convertcodetomarkdown"""importosimportrefromdatetimeimportdatetime#需要过滤的文件夹exclude_dirs=["__pycache__","venv","build","dist","node_mo......