概述

今天是构造,题似乎不是很难,然而我挂的很惨。

期望:$100+30+60+100=290$​,实际 $0+20+0+5=25$​。大家都挂的很惨,于是我 RK13/23。。。

前言

实际上我从来没有做过构造题,唯一的是前一天听同学口胡的一道 CF $1000+$​ 分的题,于是今天十分没底。

赛时

看到保证 T1 是最简单的题,我立马定好策略:切掉 T1 再说。(T1:CF1439A2

于是开始想,大概想了十分钟吧,思路就已经成型了:枚举每个 $2\times 2$​​ 正方形左上角的点,从第一行扫到倒数第三行,扫的时候保证该行所有 $1$ 都已经变成 $0$,其他随意。接着横着扫倒数第二行,一直扫到倒数第三列。这个时候除了右下角 $2\times2$ 的四个数,所有数都已经变为 $0$ 了。而对于最后四个数,可能的剩余未熄灭灯数只有 $5$​​ 种。直接用打表/分类讨论之类的方法搞出来就行。

{% spoiler Code %}

#include<bits/stdc++.h>
#define mm(x) memset(x, 0, sizeof(x))
using namespace std;
int T, n, m, a[110][110];
struct node
{
    int x, y;
};
vector<node> p;
void upd(int x, int y, int &q)
{
    p.push_back((node){x, y});
    a[x][y] = a[x][y] == 1 ? 0 : 1;
    q--;
}
int b[4][4];	
void solve_1()
{	
    int cnt = 3;
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 2; j++)
            if (a[n - i][m - j] == 1)
                upd(n - i, m - j, cnt);
}
void solve_2()
{
    mm(b);
    int cnt = 3;
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 2; j++)
            if (a[n - i][m - j] == 0)
                upd(n - i, m - j, cnt), b[i][j] = 1;
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 2; j++)
            if (!b[i][j])
                upd(n - i, m - j, cnt);
    solve_1();
}
void solve_3()
{
    mm(b);
    int cnt = 3;
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 2; j++)
            if (a[n - i][m - j] == 1)
                upd(n - i, m - j, cnt), b[i][j] = 1;
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 2; j++)
            if (!b[i][j])
                upd(n - i, m - j, cnt), b[i][j] = 1;
    solve_2();
}
void solve_0()
{
    int cnt = 3;
    upd(n, m, cnt);
    upd(n, m - 1, cnt);
    upd(n - 1, m, cnt);
    solve_3();
}
void out_put()
{
    cout << p.size() / 3;
    for (int i = 0; i < p.size(); i++)
    {
        if (i % 3 == 0)
            cout << "\n";
        cout << p[i].x << " " << p[i].y << " ";
    }
    cout << "\n";
}
int main()
{
    freopen("bulb.in", "r", stdin);
    freopen("bulb.out", "w", stdout);
    ios::sync_with_stdio(false);
    cin >> T;
    while (T--)
    {
        cin >> n >> m;
        p.clear();
        char ch;
        int ans = 0;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                cin >> ch, a[i][j] = ch == '0' ? 0 : 1;
        for (int i = 1; i < n - 1; i++)
            for (int j = 1; j < m; j++)
            {
                int cnt = 3;
                if (a[i][j] == 1)
                    upd(i, j, cnt);
                if (a[i][j + 1] == 1)
                    upd(i, j + 1, cnt);
                if (cnt == 3)
                    continue;
                if (cnt)
                    upd(i + 1, j, cnt);
                if (cnt)
                    upd(i + 1, j + 1, cnt);
            }
        for (int j = 1; j < m - 1; j++)
        {
            int cnt = 3;
            if (a[n - 1][j] == 1)
                upd(n - 1, j, cnt);
            if (a[n][j] == 1)
                upd(n, j, cnt);
            if (cnt == 3)
                continue;
            if (cnt)
                upd(n - 1, j + 1, cnt);
            if (cnt)
                upd(n, j + 1, cnt);
        }
        int tot = 0;
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
            {
                tot += a[n - i][m - j];
            }
        tot = 4 - tot;
        if (tot == 0)
            solve_0();
        else if (tot == 1)
            solve_1();
        else if (tot == 2)
            solve_2();
        else if (tot == 3)
            solve_3();
        out_put();
    }
    return 0;
}

{% endspoiler %}

写完 T1,按传统规矩自然是 DEBUG 了好久,确定无误之后已经过去一个半小时了,感觉自己得了 $100$ 分,一阵狂喜,赶快开下面的题。

接着看后面的题,决定先打暴力。

首先打了个 T3 的 $60$ 分暴力,一阵狂喜,然后去写 T4,分析了一下发现我似乎能切。于是开始写,但是调到心态爆炸,于是在剩余 $20\text{min}$​​ 的时候勉强调完了。

T2 急的一笔,快速打了个暴力,希望能得 $30$ 分。不过也没测试,草草收场了。

然后快结束的时候有人告诉我 T1 的文件名写错了,我:???

结果还真写错了,我连忙改文件名和 freopen 里的文件名。

时间到了,我一看,我 freopen 里的文件名没改上,我:???发生什么事了???

行吧, $100$ 分没了。

赛后

我一看分数就傻眼了。

再一看:T3 File Error:“未找到选手输出文件”

哦,仔细一看,我把一个 freopen 的文件名写错了,好家伙,这又少了 $60$ 分。

T4 果然挂了,不出所料,不过我和 Solution 的思路是差不多的,但是实现似乎有点问题。

又在 OJ 上交了一发,好家伙,T1 直接 AC 了,T3 $60$ 分了。

忽然意识到,我因为 freopen 痛失了 $100+60=160$ 分。太伤了,加上这些分我似乎能进 Rank 5。

题目都不是很难,T2 其实是个分类讨论题,感觉再来点时间也能想出来,倒是 T3 似乎思维难度最大,有点类似染色(

总结

狂喜把自己狂喜没了,这次在做题上还算是比较完美的,不过下一次必须认真比对文件名之后(或者直接复制)再去搞下一道题。

这次太着急了,所以出了一堆错误。

T1 明明几分钟就想出来正解了,结果后面又否定自己,最后又发现自己是对的,也浪费了大量时间。

代码实现的时候也浪费了时间。

只能说码力还是不够,正解和暴力都写得太慢了,结果没有时间支持我深入思考每道题,相信随着刷题数的增多我这个能力能增强的。