do_while_true

一言(ヒトコト)

「题解」Codeforces 741C Arpa’s overnight party and Mehrdad’s silent entering

直接无脑随机调整!

大力钦点 \(121212\cdots\) 分配。

有限制的之间记录一下,强制改成相反的,此后其中一个改变另一个也要改变。

这个时候可能不满足相邻三个不能都相同了,把冲突的拉到一个队列里面,每次取出队头随机钦点一个修改,再把修改后新产生的冲突拉到队列里面去。

复杂度玄学,实测跑的飞快。

#include<iostream>
#include<cstdio>
#include<queue>
#include<ctime>
#include<algorithm>
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T& read(T& r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
const int N = 1000010;
int n;
int to[N], pai[N][2];
int lastpos(int x) { return (x-2+n)%n+1; }
int nextpos(int x) { return x%n+1; }
int a[N];
bool vis[N];
std::queue<int>q;
bool chk(int i) {return (a[i] == a[nextpos(i)] && a[nextpos(i)] == a[nextpos(nextpos(i))]); }
void chk2(int pos) {
	if(chk(pos)) {
		if(!vis[pos]) q.push(pos);
		vis[pos] = 1;
	}
	else vis[pos] = 0;
	if(chk(lastpos(pos))) {
		if(!vis[lastpos(pos)]) q.push(lastpos(pos));
		vis[lastpos(pos)] = 1;
	}
	else vis[lastpos(pos)] = 0;
	if(chk(lastpos(lastpos(pos)))) {
		if(!vis[lastpos(lastpos(pos))]) q.push(lastpos(lastpos(pos)));
		vis[lastpos(lastpos(pos))] = 1;
	}
	else vis[lastpos(lastpos(pos))] = 0;
	if(chk(nextpos(pos))) {
		if(!vis[nextpos(pos)]) q.push(nextpos(pos));
		vis[nextpos(pos)] = 1;
	}
	else vis[nextpos(pos)] = 0;
	if(chk(nextpos(nextpos(pos)))) {
		if(!vis[nextpos(nextpos(pos))]) q.push(nextpos(nextpos(pos)));
		vis[nextpos(nextpos(pos))] = 1;
	}
	else vis[nextpos(nextpos(pos))] = 0;
}
signed main() { //freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);
	srand(time(NULL)^(unsigned)(* new char));
	read(n); bool fl = 0; n <<= 1;
	for(int i = 1; i <= n/2; ++i) {
		int x, y; read(x); read(y);
		pai[i][0] = x; pai[i][1] = y;
		to[x] = y; to[y] = x;
		if(!(y == (x-2+n)%n+1 || y == x%n+1)) fl = 1;
	}
	for(int i = 1; i <= n; ++i) a[i] = i&1;
	for(int i = 1; i <= n; ++i)
		if(a[i] == a[to[i]])
			a[to[i]] = !a[to[i]];
	for(int i = 1; i <= n; ++i) {
		vis[i] = chk(i);
		if(vis[i])
			q.push(i);
	}
	while(!q.empty()) {
		int x = q.front(); q.pop();
		if(!chk(x)) continue ;
		int pos = rand()%2+1;
		if(pos == 1) pos = x;
		else if(pos == 2) pos = nextpos(x);
		else if(pos == 3) pos = nextpos(nextpos(x));
		a[pos] = !a[pos]; a[to[pos]] = !a[to[pos]];
		chk2(pos); chk2(to[pos]);
	}
	for(int i = 1; i <= n/2; ++i)
		printf("%d %d\n", 2-a[pai[i][0]], 2-a[pai[i][1]]);
	return 0;
}
posted @ 2021-08-16 09:48  do_while_true  阅读(42)  评论(0编辑  收藏  举报