P9731 [CEOI2023] Balance 题解

首先考虑 \(S=2\) 怎么做,我们把它转化为图论问题。对于每一行的两个点的颜色连一条无向边,那我们相当于要给这些边定向。最后要求 \(|in_u-out_u| \le 1\)。会发现这个要求很像欧拉回路。

但是欧拉回路是要求每个点的入度和出度相等,怎么办呢?我们再建一个超级源点,向每个奇数度数的点连边。这样跑一遍欧拉回路,最后忽略和超级源点相连的边即可。

问题变为了 \(S > 2\) 怎么做。因为题目说 \(S\)\(2\) 的次幂,这让我们想到分治。每一次只需要要求每种颜色在左一半的出现次数和在右一半的出现次数差不超过 \(1\)。但是题目要求我们只能在行内交换,所以假设我们现在分治到 \([l,r]\),我们就连边 \((a_{i,j},a_{i,mid+1+j-l})\)。会发现这样一定有解。

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

//dzzfjldyqqwsxdhrdhcyxll
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 4e6 + 10;
int n,s,t,head[MAXN],cnt,vis[MAXN << 1],ans[MAXN << 1],tot,d[MAXN << 1];
struct Node {int u,v,nxt;}e[MAXN << 1];
inline void Add(int u,int v) {
//	cout << "u = " << u << " v = " << v << endl; 
	e[cnt] = {u,v,head[u]};
	head[u] = cnt++;
}
vector <int> a[MAXN];
inline int Get(int i,int j) {
	return max(t,n * s) + (i - 1) * s + j; 
}
inline void dfs(int u) {
	for(int &i = head[u]; ~ i;i = e[i].nxt) {
		if(vis[i]) continue;
		int now = e[i].v;
		vis[i] = vis[i ^ 1] = 1;
		dfs(now);
		if(i==-1){
			break;
		}
	}
	ans[++tot] = u;
//	cout << u << " ";
}
inline void solve(int l,int r) {
	int mid = (l + r) >> 1;
	for(int i = 1;i <= n;i++) {
		for(int j = l;j <= mid;j++) {
			if(a[i][j] == a[i][mid + 1 + j - l]) continue;
			Add(a[i][j],Get(i,j));
			Add(Get(i,j),a[i][j]);
			Add(Get(i,j),a[i][mid + 1 + j - l]);
			Add(a[i][mid + 1 + j - l],Get(i,j));
			d[a[i][j]]++;
			d[a[i][mid + 1 + j - l]]++;
		}
	}
	if(l == 3 && r == 4) {
//		cout << "dddd = " << d[3] << endl;
	}
	for(int i = 1;i <= n;i++) {
		for(int j = l;j <= r;j++) {
			if(d[a[i][j]] % 2 == 1) {
				d[a[i][j]]++;
				Add(0,a[i][j]);
				Add(a[i][j],0);
			}
		}
	}
	tot = 0;
//	dfs(0);
	for(int i = 1;i <= n;i++) {
		for(int j = l;j <= r;j++) {
//			cout << endl << endl << endl;
			dfs(a[i][j]);
		}
	}
	for(int i = 1;i <= tot;i++) {
		if(l == 3 && r == 4) {
//			cout << "ans = " << ans[i] << endl;
		}
		if(ans[i] > max(t,n * s)) {
			int val = ans[i] - max(t,n * s);
			int x = (val - 1) / s + 1;
			int y = (val % s == 0 ? s : val % s);
			if(ans[i - 1] == a[x][y]);
			else swap(a[x][y],a[x][mid + 1 + y - l]);
		}
	}
	d[0] = 0;
	head[0] = -1;
	for(int i = 1;i <= n;i++) {
		for(int j = l;j <= r;j++) {
			d[a[i][j]] = 0;
			head[a[i][j]] = -1;
			d[Get(i,j)] = 0;
			head[Get(i,j)] = -1;
		}
	}
	for(int i = 0;i < cnt;i++) {
		vis[i] = 0;
		d[e[i].u] = 0;
		d[e[i].v] = 0;
		head[e[i].u] = -1;
		head[e[i].v] = -1;
	}
//	memset(d,0,sizeof d);
//	memset(vis,0,sizeof vis);
//	memset(head,-1,sizeof head);
	cnt = 0;
//	cout << "l = " << l << " r = " << r << endl;
//	for(int i = 1;i <= n;i++,puts(""))
//		for(int j = 1;j <= s;j++) cout << a[i][j] << " ";
	if(r - l == 1) return; 
	solve(l,mid),solve(mid + 1,r);
	return; 
} 
signed main() { 
//	freopen("P9731_23.in","r",stdin);
	memset(head,-1,sizeof head);
	cin >> n >> s >> t;
	for(int i = 1;i <= n;i++) {
		a[i].resize(s + 5); 
	}
	for(int i = 1;i <= n;i++) {
		for(int j = 1;j <= s;j++) {
			cin >> a[i][j];
		}
	}
	solve(1,s);
	for(int i = 1;i <= n;i++,puts("")) {
		for(int j = 1;j <= s;j++) {
			cout << a[i][j] << " ";
		}
	}	
	return 0;
}
/*
3 8 5
2 3 5 1 5 5 4 4
3 5 1 1 2 3 2 2
1 3 3 2 2 5 3 4
3 2 5
4 1 
3 5
2 3
*/
posted @ 2024-10-17 11:13  Creeper_l  阅读(13)  评论(0编辑  收藏  举报
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 世间美好与你环环相扣 柏松
  3. 3 True love tired
  4. 4 一笑江湖 (DJ弹鼓版) 闻人听書_
  5. 5 最好的安排 曲婉婷
  6. 6 星星在唱歌 司南
  7. 7 山川 李荣浩
  8. 8 On My Way Alan Walker
  9. 9 百战成诗 王者荣耀·100英雄官方群像献礼歌
  10. 10 雪 Distance Capper / 罗言
  11. 11 Edamame bbno$ / Rich Brian
  12. 12 半生雪 七叔-叶泽浩
  13. 13 Catch My Breath Kelly Clarkson
  14. 14 Love Is Gone SLANDER / Dylan Matthew
  15. 15 Endless Summer Alan Walker / Zak Abel
  16. 16 悬溺 葛东琪
  17. 17 风吹丹顶鹤 葛东琪
  18. 18 Normal No More TYSM
  19. 19 哪里都是你 队长
  20. 20 Stronger Kelly Clarkson
  21. 21 廖俊涛
  22. 22 消愁 毛不易
  23. 23 The Runner Yubik
  24. 24 踏山河 七叔-叶泽浩
  25. 25 Waiting For Love Avicii
  26. 26 在你的身边 盛哲
  27. 27 Dream It Possible Delacey
  28. 28 凄美地 郭顶
  29. 29 满天星辰不及你 ycc
  30. 30 侧脸 于果
  31. 31 阿拉斯加海湾 蓝心羽
  32. 32 虞兮叹 闻人听書_
  33. 33 离别开出花 就是南方凯
  34. 34 盗墓笔记·十年人间 李常超 (Lao乾妈)
Waiting For Love - Avicii
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.