Boring Card Game

· · 题解

Boring Card Game

我愿意称之为最水的黑题。

#include <bits/stdc++.h>
#define LL long long
#define Re register int
#define LD double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(Re x = y; x <= z; x ++)
#define fp(x, y, z)for(Re x = y; x >= z; x --)
#define delfr(x, y, z)for(Re x = y; x < z; x ++)
#define delfp(x, y, z)for(Re x = y; x > z; x --)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')
#define WMX aiaiaiai~~
#define pr(x, y) pair<x, y>
#define mk(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define re(x) return x
#define sec second
#define fst first

using namespace std;
namespace kiritokazuto{
    auto read = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template  <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}

using namespace kiritokazuto;

const int maxn = 2000 + 5, maxm = 6e5+ 5, Mod = 993244853;
const LL Inf = 0x7fffffffffff;

int stk[maxn];
int bel[maxn];//块里点的类型
int top;
int n;
int deg[maxn];
int fa[maxn];
int rem[maxn][4];
int type[maxn];//1 先手 0 后手
int q[maxn], l, r;//topo
int tot[maxn];//一个块里有几个点
int num;//总共有多少块
int now = 1;//现在谁取
int vis[maxn];
signed main() {
    n = read();
    n *= 3;
    fr(i, 1, n) type[read()] = 1;
    n <<= 1;
    fr(i, 1, n) {
        if(!top || bel[stk[top]] != type[i]) {//没块或者与栈顶不同类,加新的
            bel[++num] = type[i];
            stk[++top] = num;
            rem[num][++tot[num]] = i;
        }else {
            rem[stk[top]][++tot[stk[top]]] = i;
            if(tot[stk[top]] == 3){
                fa[stk[top]] = stk[top - 1];
                top--;
            }
        }
    }
    int mach = 0;//以0为根的点有几个
    fr(i, 1, num) {
        if(!fa[i] && !bel[i])mach ++;
        deg[fa[i]]++;//出度
    }

    fr(i, 1, num){//我当前处理第几个节点
        fr(j, 1, num) {
            if(!deg[j] && bel[j] == now && !vis[j]) {
                if(i < num && (bel[j] == 0) && mach == 1 && !fa[j])continue;
                //不是最后一个的话我们不能将最后一个作为根的后手取走
                vis[j] = 1;
                deg[fa[j]]--;
                if(!bel[j] && !fa[j])mach--;
                printf("%d %d %d\n", rem[j][1], rem[j][2], rem[j][3]);
                break;
            }
        }
        now ^= 1;
    } 
    re(0);

}