题解 P7946 【Yet Another Cirno Game】
算是官方题解(
该问题可以转化为:有一个
定义 「
显然,一个
如果我们先按上述方式把能消的列都消了,那么我们会发现只会剩下
那么我们考虑先在一开始把多余的
第一种拿两个位置不同的
这么消完以后,会发现只剩下
第二种是拿一个第
第三种是拿一个第
如果还有剩下的
按照上述顺序模拟过程即可。记得将多余的
为什么这样最优呢?因为第
#include <bits/stdc++.h>
#define tn (2 * n)
using namespace std;
const int N = 2e6 + 7;
int f[N][4];
int a[2 * N], cnt[N], n, ans[2 * N], anss[4 * N], siz[5], mp[4 * N], tmp, dif;
int p[5][N];
bool used[N];
int v[4][N], sizz[4];
bool chg = false;
#define re register
inline int read()
{
re int x=0,f=1;re char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
int*GP(){static int x[]{0,1,2,3};sort(x,x+4,[](int x,int y){return sizz[x] > sizz[y];});return x;}
void out(){
for(int p0, p4, i = 0; i < siz[0]; i++){
p0 = p[0][i], p4 = p[4][i];
for(int j = 0; j < 4; j++) f[p0][j] = f[p4][j] + tn;
}
int po = 0;
for(int p1, p3, i = 0; i < siz[1]; i++){
p1 = p[1][i], p3 = p[3][po];
if(used[p1]) continue;
while(used[p3]) po++, p3 = p[3][po];
int v1 = 0, v2 = -1, v3 = 0, v4 = 0;
bool flag = false;
for(int j = 0; j < 4; j++) if(f[p1][j] && !f[p3][j]) flag = true, v1 = j;
if(!flag){
for(int j = 0; j < 4; j++){
if(f[p1][j]) v1 = j;
else if(!f[p3][j]) v4 = j;
else v2 != -1 ? v3 = j : v2 = j;
}
}
if(flag){
for(int j = 0; j < 4; j++){
if(v1 == j) f[p3][j] = f[p1][j] + tn;
else f[p1][j] = f[p3][j] + tn;
}
}else{
f[p1][v4] = f[p1][v1] + tn;
f[p3][v4] = f[p3][v1] + tn;
f[p1][v2] = f[p3][v2] + tn;
f[p1][v3] = f[p3][v3] + tn;
}
po++;
}
for(int p2, i = 0; i < siz[2]; i++){
p2 = p[2][i];
if(used[p2]) continue;
int v1 = -1, v2, v3 = -1, v4;
for(int j = 0; j < 4; j++){
if(f[p2][j]) v1 != -1 ? v2 = j : v1 = j;
else v3 != -1 ? v4 = j : v3 = j;
}
f[p2][v3] = f[p2][v1] + tn;
f[p2][v4] = f[p2][v2] + tn;
}
printf("%d\n", tn - dif);
for(int i = 0; i < n; i++){
for(int j = 0; j < 4; j++){
if(f[i][j] > tn && chg) anss[mp[i + j * n]] = f[i][j] - tn - 1;
if(f[i][j] <= tn && chg) ans[f[i][j] - 1] = i + j * n;
if(f[i][j] > tn && !chg) ans[f[i][j] - tn - 1] = i + j * n;
}
}
for(int i = 0; i < tn; i++) printf("%d ", chg ? ans[anss[i]] : ans[i]);
exit(0);
}
int main(){
n = read();
for(int i = 0; i < tn; i++) a[i] = read(), f[a[i] % n][a[i] / n] = i + 1, cnt[a[i] % n]++, mp[a[i]] = i;
for(int i = 0; i < n; i++) p[cnt[i]][siz[cnt[i]]] = i, siz[cnt[i]]++;
if(siz[1] < siz[3]){
chg = true;
swap(siz[0], siz[4]);
swap(siz[1], siz[3]);
swap(p[0], p[4]);
swap(p[1], p[3]);
tmp = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < 4; j++){
if(f[i][j]) f[i][j] = 0;
else f[i][j] = ++tmp;
}
}
}
for(int i = 0; i < siz[1]; i++){
for(int j = 0; j < 4; j++){
if(f[p[1][i]][j]){
v[j][sizz[j]++] = p[1][i];
}
}
}
dif = siz[4] - siz[0];
while(dif){
int p4 = p[4][siz[4] - 1], v1 = GP()[0], v2 = GP()[1], v3 = -1, v4;
if(!sizz[v2]) break;
int p11 = v[v1][sizz[v1] - 1], p12 = v[v2][sizz[v2] - 1];
for(int i = 0; i < 4; i++){
if(i != v1 && i != v2) v3 != -1 ? v4 = i : v3 = i;
}
f[p12][v1] = f[p4][v1] + tn;
f[p11][v2] = f[p4][v2] + tn;
f[p12][v3] = f[p4][v3] + tn;
f[p11][v4] = f[p4][v4] + tn;
f[p11][v3] = f[p11][v1] + tn;
f[p12][v4] = f[p12][v2] + tn;
used[p4] = true, used[p11] = true, used[p12] = true;
dif--, siz[4]--, sizz[v1]--, sizz[v2]--;
}
if(!dif) out();
int v1 = GP()[0];
for(int i = 0; i < siz[2]; i++){
int p2 = p[2][i];
if(f[p2][v1]) continue;
int p11 = v[v1][sizz[v1] - 1], p12 = v[v1][sizz[v1] - 2], p4 = p[4][siz[4] - 1];
int v2 = -1, v3 = 0, v4;
for(int j = 0; j < 4; j++){
if(!f[p2][j] && j != v1) v4 = j;
else if(j != v1) (v2 != -1 ? v3 = j : v2 = j);
}
f[p2][v1] = f[p4][v1] + tn;
f[p2][v4] = f[p4][v4] + tn;
f[p11][v4] = f[p11][v1] + tn;
f[p12][v4] = f[p12][v1] + tn;
f[p11][v2] = f[p4][v2] + tn;
f[p11][v3] = f[p4][v3] + tn;
f[p12][v2] = f[p2][v2] + tn;
f[p12][v3] = f[p2][v3] + tn;
used[p4] = true, used[p2] = true, used[p11] = true, used[p12] = true;
dif--, siz[4]--, sizz[v1] -= 2;
if(!dif) out();
}
for(int i = 0; i < siz[3]; i++){
if(sizz[v1] == 2) break;
int p3 = p[3][i];
if(f[p3][v1]) continue;
int p11 = v[v1][sizz[v1] - 1], p12 = v[v1][sizz[v1] - 2], p13 = v[v1][sizz[v1] - 3], p4 = p[4][siz[4] - 1];
int v2 = -1, v3 = -1, v4 = 0;
for(int j = 0; j < 4; j++) if(j != v1) v2 != -1 ? (v3 != -1 ? v4 = j : v3 = j) : v2 = j;
f[p3][v1] = f[p4][v1] + tn;
f[p11][v2] = f[p11][v1] + tn;
f[p12][v3] = f[p12][v1] + tn;
f[p13][v4] = f[p13][v1] + tn;
f[p12][v2] = f[p4][v2] + tn;
f[p13][v2] = f[p3][v2] + tn;
f[p11][v3] = f[p4][v3] + tn;
f[p13][v3] = f[p3][v3] + tn;
f[p11][v4] = f[p4][v4] + tn;
f[p12][v4] = f[p3][v4] + tn;
used[p4] = true, used[p3] = true, used[p11] = true, used[p12] = true, used[p13] = true;
dif--, siz[4]--, sizz[v1] -= 3;
if(!dif) out();
}
for(int i = 0; i < dif; i++){
int p11 = v[v1][sizz[v1] - 1], p12 = v[v1][sizz[v1] - 2], p4 = p[4][siz[4] - 1];
int v2 = -1, v3 = -1, v4 = 0;
for(int j = 0; j < 4; j++) if(j != v1) v2 != -1 ? (v3 != -1 ? v4 = j : v3 = j) : v2 = j;
f[p12][v4] = f[p4][v1] + tn;
f[p11][v2] = f[p11][v1] + tn;
f[p12][v3] = f[p12][v1] + tn;
f[p12][v2] = f[p4][v2] + tn;
f[p11][v3] = f[p4][v3] + tn;
f[p11][v4] = f[p4][v4] + tn;
used[p4] = true, used[p11] = true, used[p12] = true;
siz[4]--, sizz[v1] -= 2;
}
out();
return 0;
}