codeforces1472F New Year‘s Puzzle(发现规律)

传送门
题解:刚开始没看数据范围,以为都是 2 e 5 2e5 2e5 ,被很残忍的坑了一波,我分了 10 10 10 个状态进行线性 d p dp dp ,最后在 3 3 3 R E RE RE,附上辛酸史

#include 
using namespace std;

int main()
{
     
    int T;
    cin >> T;
    while (T--) {
     
        int n, m, r, c;
        cin >> n >> m;
        vector<vector<int>> g(2, vector<int> (n, 0));
        for (int i = 0; i < m; i++) {
     
            cin >> r >> c;
            r--; c--;
            g[r][c] = 1;
        }
        vector<vector<vector<int>>> d(n, vector<vector<int>> (4, vector<int> (4, 0)));
        bool flag=true;
        if (g[0][0] == 0 && g[1][0] == 0) {
     
            d[0][0][0] = 1;
            if (n > 1) {
     
                if (g[0][1] == 0 && g[1][1] == 0) {
     
                    d[0][2][2] = 1;
                }
            }
        } else if (g[0][0] == 1 && g[1][0] == 0) {
     
            if (n > 1 && g[1][1] == 0) {
     
                d[0][3][2] = 1;
            }
        } else if (g[1][0] == 1 && g[0][0] == 0) {
     
            if (n > 1 && g[0][1] == 0) {
     
                d[0][2][3] =1;
            }
        } else {
     
            d[0][3][3] = 1;
        }
        int i = 0;
        if (n == 1 && (d[i][0][0] | d[i][1][1] | d[i][2][2] | d[i][1][2] | d[i][2][1] | d[i][3][3] | d[i][3][1] | d[i][3][2] | d[i][2][3] | d[i][1][3]) == 0) {
     
            flag = false;
        }
        // int i = 0;
        // cout << d[0][0][0] << " " << d[i][1][1] << " " << d[i][2][2] << " " << d[i][1][2] << " " << d[i][2][1] << endl;
        // cout << d[0][3][3] << " " << d[i][3][1] << " " << d[i][3][2] << " " << d[i][2][3] << " " << d[i][1][3] << endl;
        for (int i = 1; i < n; i++) {
     
            if (g[0][i] == 0 && g[1][i] == 0) {
     
                d[i][0][0] = d[i - 1][0][0] | d[i - 1][1][1] | d[i - 1][3][3] | d[i - 1][3][1] | d[i - 1][1][3];
                d[i][1][1] = d[i - 1][2][2];
                if (i + 1 < n && g[0][i + 1] == 0 && g[1][i + 1] == 0) {
     
                    d[i][2][2] = d[i - 1][0][0] | d[i - 1][1][1] | d[i - 1][3][3] | d[i - 1][3][1] | d[i - 1][1][3];
                }
                if (i + 1 < n && g[1][i + 1] == 0) {
     
                    d[i][1][2] = d[i - 1][2][1] | d[i - 1][2][3];
                }
                if (i + 1 < n && g[0][i + 1] == 0) {
     
                    d[i][2][1] = d[i - 1][1][2] | d[i - 1][3][2];
                }
            } else if (g[0][i] == 1 && g[1][i] == 0) {
     
                d[i][3][1] = d[i - 1][1][2] | d[i - 1][3][2];
                if (i + 1 < n && g[1][i + 1] == 0) {
     
                    d[i][3][2] = d[i - 1][0][0] | d[i - 1][1][1] | d[i - 1][3][3] | d[i - 1][3][1] | d[i - 1][1][3];
                }
            } else if (g[1][i] == 1 && g[0][i] == 0) {
     
                d[i][1][3] = d[i - 1][2][3] | d[i - 1][2][1];
                if (i + 1 < n && g[0][i + 1] == 0) {
     
                    d[i][2][3] = d[i - 1][0][0] | d[i - 1][1][1] | d[i - 1][3][3] | d[i - 1][3][1] | d[i - 1][1][3];
                }
            } else {
     
                d[i][3][3] = d[i - 1][0][0] | d[i - 1][1][1] | d[i - 1][3][3] | d[i - 1][3][1] | d[i - 1][1][3];
            }
            // cout << d[i][0][0] << " " << d[i][1][1] << " " << d[i][2][2] << " " << d[i][1][2] << " " << d[i][2][1] << endl;
            // cout << d[i][3][3] << " " << d[i][3][1] << " " << d[i][3][2] << " " << d[i][2][3] << " " << d[i][1][3] << endl;
            if ((d[i][0][0] | d[i][1][1] | d[i][2][2] | d[i][1][2] | d[i][2][1] | d[i][3][3] | d[i][3][1] | d[i][3][2] | d[i][2][3] | d[i][1][3]) == 0) {
     
                flag = false;
                break;
            }
        }
        cout << (flag == true ? "YES" : "NO") << endl;
    }
    return 0;
}

然后看了眼数据范围, n n n 1 e 9 1e9 1e9 ,那么再思考思考,发现了规律,就是如果障碍数不是 2 2 2 的倍数,那么直接凉凉,是 2 2 2 的倍数的话,那么比如 ( 1 , 5 ) (1, 5) (1,5) 是从左往右第一个障碍,要想最后铺满,那么情况一:在 ( 2 , 5 ) (2, 5) (2,5) 这个位置要么有个砖块在 ( 2 , 4 ) (2,4) (2,4) ( 2 , 5 ) (2,5) (2,5) ,要么情况二: ( 2 , 5 ) (2,5) (2,5) ( 2 , 6 ) (2,6) (2,6) ,可是想下,情况一不能成立的好吧,情况一成立了, 前面那几排就有空格了,只能考虑情况二,然后考虑接下来最近的障碍,发现如果最近的往后两个障碍都是一列的,那么直接凉凉,如果最近的障碍是同一行的,那么中间间隔只能是偶数个空格,如果不是同一行的,那么中间间隔只能是奇数个,除非最近的那个障碍和本障碍同一列,不然都是凉凉。

#include 
using namespace std;
int main()
{
     
    int T;
    cin >> T;
    while (T--) {
     
        int n, m;
        cin >> n >> m;
        vector<pair<int,int>> v(m);
        bool flag = true;
        for (auto &x : v) {
     
            cin >> x.second >> x.first;
        }
        sort(v.begin(), v.end());
        if (m % 2 == 1) {
     
            flag = false;
        } else {
     
            for (int i = 0; i < m; i++) {
     
                if (i + 1 < m) {
     
                    int c = (v[i + 1].first - v[i].first) % 2, f = (v[i + 1].second == v[i].second);
                    if (v[i + 1].first != v[i].first && c + f == 1) {
     
                        flag = false;
                        break;
                    }
                }
                if (i + 2 < m && v[i + 2].first == v[i + 1].first) {
     
                    flag = false;
                    break;
                }
                i++;
            }
        }
        cout << (flag ? "YES" : "NO") << endl;
    }
    return 0;
}

你可能感兴趣的:(日常code)