2020牛客多校第三场D-Point Construction Problem

https://ac.nowcoder.com/acm/contest/5668/D

题意

无穷大平面上,初始全是白点,问能否放置n个黑点,使得相邻的黑白点对的数目恰好为m,给出一种放置方法

题解

首先,如果m是奇数肯定无解,因为从每一行和每一列看过去,黑点的两侧必定有两个白点。

显然一个黑点最多形成4个黑白点对,所以\(m > 4n\)也无解

因为对于每一行黑点和每一列黑点,都贡献2的答案,所以我们可以遍历行数和列数,计算最小的答案,小于这个答案也无解。

其余情况必定有解,我们先按答案最小时放置,之后取出点单独放置,答案会增加2或者增加4,如果增加4后答案超过m,则把单独放置的点重新摆到第一排即可。

代码

#include <bits/stdc++.h>
#define pii pair<int, int>
using namespace std;
typedef long long ll;
struct READ {
    inline char read() {
    #ifdef _WIN32
        return getchar();
    #endif
        static const int IN_LEN = 1 << 18 | 1;
        static char buf[IN_LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        static char c11, boo;
        for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
            if(c11 == -1) return *this;
            boo |= c11 == '-';
        }
        for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
        boo && (x = -x);
        return *this;
    }
} in;

const int N = 2e5 + 50;
int main() {
    int t; in >> t;
    while (t--) {
        int n, m;
        in >> n >> m;
        if (m > 4 * n || (m & 1)) puts("No");
        else {
            
            int a, b, mn = 1e9;
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    if (i * j >= n && (i + j) * 2 < mn) {
                        mn = 2 * (i + j);
                        a = i, b = j;
                    }
                }
            }
            vector<pii> ans;
            vector<pii> ans2;
            int tmp = n;
            for (int i = 1; i <= a; i++) {
                for (int j = 1; j <= b; j++) {
                    ans.push_back(pii(i, j));
                    tmp--;
                    if (tmp == 0) break;
                }
            }
            int now = 2 * (a + b);
            if (m < now) {
                puts("No");
                continue;
            }
            puts("Yes");
            int x = 1e8, y = 1e8;
            while (now < m) {
                pii p = ans.back();
                if (p.second == 1 || p.first == 1) {
                    ans.pop_back();
                    now += 2;
                    ans2.push_back(pii(--x, --y));
                }
                else {
                    ans.pop_back();
                    now += 4;
                    ans2.push_back(pii(--x, --y));
                }
            }
            if (now > m) {
                ans2.pop_back();
                pii p = ans.back();
                ans.push_back(pii(p.first + 1, p.second));
            }
            for (auto e : ans) printf("%d %d\n", e.first, e.second);
            for (auto e : ans2) printf("%d %d\n", e.first, e.second);
        }
    }
    return 0;
}
posted @ 2020-08-31 14:51  Artoriax  阅读(128)  评论(0编辑  收藏  举报