codeforces 构造题专题(easy version)

1.CF1768C Elemental Decompress(*1300 贪心、构造)

参考@此处

s1s2表示仍未填入p[]q[]中的数字。

贪心策略:

将未重复的数尽量填入p[]中,重复的数填入q[]中,同时更新s1s2

对于q[]中每一位未填的数,贪心选择s2中最大的数且该数pip[]的处理相同。

参考做法的代码相当优美,学到很多。

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define cerr(x) std::cerr << (#x) << " is " << (x) << '\n'
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
#define PII pair<int, int>
#define pdd pair<double,double>
#define PLL pair<LL,LL>

#define LL long long

const double CLOCKS_PER_SECOND = ((clock_t) 1000);
const double CLOCKS_PER_MILLISECOND = ((clock_t) 1);
const int N = 2e5 + 10, M = 1e8, mod = 1e9 + 7, inf = 0x3f3f3f3f;
const double eps = 1e-6;
//#define x first
//#define y second

int T;


bool cmp(PII &a, PII &b) {
    return a.second < b.second;
}

bool cmp2(PII &a, PII &b) {
    return a.first < b.first;
}

void solve() {
    int n, Max = -1;
    cin >> n;
    vector<int> a(n);
    set<int> s1, s2;
    for (auto &ai: a) cin >> ai, Max = max(Max, ai);
    if (Max < n) {
        cout << "NO" << endl;
        return;
    }
    vector<int> p(n), q(n);
    for (int i = 1; i <= n; i++) s1.insert(i), s2.insert(i);
    for (int i = 0; i < n; i++) {
        if (s1.count(a[i])) s1.erase(p[i] = a[i]);
        else if (s2.count(a[i])) s2.erase(q[i] = a[i]);
        else {
            cout << "NO" << endl;
            return;
        }
    }

    for (int i = 0; i < n; i++) {
        if (!p[i]) {
            auto it = s1.lower_bound(q[i]);
            if (it != s1.end() && *it == q[i]) s1.erase(p[i] = *it);//找到了,而且值=q[i]
            else if (it == s1.begin()) {
                cout << "NO" << endl;
                return;
            } else {
                it = prev(it);
                s1.erase(p[i] = *it);
            }
        } else {
            auto it = s2.lower_bound(p[i]);
            if (it != s2.end() && *it == p[i]) s2.erase(q[i] = *it);
            else if (it == s2.begin()) {
                cout << "NO" << endl;
                return;
            } else {
                it = prev(it);
                s2.erase(q[i] = *it);
            }
        }
    }
    cout << "YES" << endl;
    for (int i = 0; i < n; i++) cout << p[i] << " \n"[i == n - 1];
    for (int i = 0; i < n; i++) cout << q[i] << " \n"[i == n - 1];
    return;
}


signed main() {
    IOS;
    cin >> T;
    while (T--)
        solve();
}

2A.Make Nonzero Sum (easy version) (*1300 贪心、构造)

因为不要求最小区间数,所以可以一个个拆开看。我们发现,a1a2+a3a4=(a1a2)+(a3a4),所以一个大区间一定能够拆分成len=21的区间。故如果n为奇数是无解的。

讨论len=2:如果两个数不相同,那么a1a2不为0,故我们贪心的将其分为{a1,a1}{a2,a2},这样两者和为0;如果相同,则直接计入一个区间{a1,a2}

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define cerr(x) std::cerr << (#x) << " is " << (x) << '\n'
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
#define PII pair<int, int>
#define pdd pair<double,double>
#define PLL pair<LL,LL>

#define LL long long


const double CLOCKS_PER_SECOND = ((clock_t) 1000);
const double CLOCKS_PER_MILLISECOND = ((clock_t) 1);
const int N = 2e5 + 10, M = 1e8, mod = 1e9 + 7, inf = 0x3f3f3f3f;
const double eps = 1e-6;
//#define x first
//#define y second

int T;

int a[N];

void solve() {
    int n;
    cin >> n;
    vector<PII > v;
    int sum = 0;
    for (int i = 1; i <= n; i++)
        cin >> a[i], sum += a[i];
    if (n & 1) {
        cout << -1 << endl;
        return;
    }
    for (int i = 1; i <= n; i += 2) {
        if (a[i] == a[i + 1]) v.push_back({i, i + 1});
        else v.push_back({i, i}), v.push_back({i + 1, i + 1});
    }
    cout << v.size() << endl;
    for (auto &i: v) cout << i.first << " " << i.second << endl;
    return;
}


signed main() {
    IOS;
    cin >> T;
    while (T--)
        solve();
}

2B.Make Nonzero Sum (hard version)(*1500 贪心、构造)

首先,可以判断出:若非0的个数为奇数时无解,原因与2A相同。

{1,1}{1,1}的情况不用再重复,我们判断如下情况:

  • {1,0...0,1}:可以拆分成{1}+{0}+...+{0,1}=0

  • {1,0...0,1}:可以拆分成{1}+{0}+...+{1}=0

前置0全部单独划分为一个区间。

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define cerr(x) std::cerr << (#x) << " is " << (x) << '\n'
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
#define PII pair<int, int>
#define pdd pair<double,double>
#define PLL pair<LL,LL>

#define LL long long


const double CLOCKS_PER_SECOND = ((clock_t) 1000);
const double CLOCKS_PER_MILLISECOND = ((clock_t) 1);
const int N = 2e5 + 10, M = 1e8, mod = 1e9 + 7, inf = 0x3f3f3f3f;
const double eps = 1e-6;
//#define x first
//#define y second

int T;

int a[N];

void solve() {
    int n;
    cin >> n;
    vector<PII > v;
    int sum = 0;
    for (int i = 1; i <= n; i++)
        cin >> a[i], sum += (a[i] != 0);
    if (sum & 1) {
        cout << -1 << endl;
        return;
    }
    for (int i = 1; i <= n;) {
        while (!a[i] && i <= n) {
            v.push_back({i, i});
            i++;
        }
        if (i > n) break;
        int l = i, r = i + 1;
        if (a[r]) {
            if (a[l] == a[r]) v.push_back({l, l + 1});
            else {
                v.push_back({l, l});
                v.push_back({l + 1, l + 1});
            }
        } else {
            v.push_back({l, l});
            while (!a[r] && r <= n) {
                v.push_back({r, r});
                r++;
            }
            if (a[l] != a[r]) v.push_back({r, r});
            else v.back().second = r;//更改为{0,1},凑成(1)+(0-1)
        }//{1,1},{0,0},1
        i = r + 1;

    }
    cout << v.size() << endl;
    for (auto &i: v) cout << i.first << " " << i.second << endl;
    return;
}


signed main() {
    IOS;
    cin >> T;
    while (T--)
        solve();
}

3.Vlad and a Pair of Numbers(*1400 位运算,构造)

a+b2=ab=x

由常见的推论得:a+b=ab+((ab)<<1)

故化简得:ab=((ab)<<1)=x

分析(x)2的取值:

  • 1.x的第i位为1,第i1位为1,不成立

  • 2.x的第i位为1,第i1位为0,成立,此时abi位不相同即满足;

  • 3.x的第i位为0,第i1位为1,成立,此时abi位均为1时满足;

  • 4.x的第i位为0,第i1位为0,成立,此时abi位均为0时满足;

分析可知,无解的情况当且仅当(x)2有连续两位为1。故对于可行解x一定是满足1 0 1 0排列的。

不妨如下构造:

(n)2[i]=1,a[i]=1,b[i]=0,a[i1]=b[i1]=1

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define cerr(x) std::cerr << (#x) << " is " << (x) << '\n'
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
#define PII pair<int, int>
#define pdd pair<double,double>
#define PLL pair<LL,LL>
#define rep(i, j, k) for(int i=j;i<=k;i++)

#define int long long


const double CLOCKS_PER_SECOND = ((clock_t) 1000);
const double CLOCKS_PER_MILLISECOND = ((clock_t) 1);
const int N = 1e6 + 10, M = 1e8, mod = 1e9 + 7, inf = 0x3f3f3f3f;
const double eps = 1e-6;
//const int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
const int dx[] = {-1, 0, 0, 1}, dy[] = {0, 1, -1, 0};
//#define x first
//#define y second
//int fac[N];

int qpow(int a, int b) {
    int ans = 1LL, base = a;
    while (b) {
        if (b & 1) ans = (ans * base) % mod;
        base = (base * base) % mod;
        b >>= 1;
    }
    return ans;
}
/*
int C(int n, int k) {
    if (k > n) return 0;
    return (fac[n] * qpow(fac[k], mod - 2) % mod) * qpow(fac[n - k], mod - 2) % mod;
}

int Lucas(int n, int k) {
    if (!k) return 1LL;
    return C(n % mod, k % mod) * Lucas(n / mod, k / mod) % mod;
}
*/
int T;
int fac[32 + 5];

void solve() {
    int n;
    cin >> n;
    vector<int> v(32 + 5), a(35, 0), b(35, 0);
    if (n & 1) {
        cout << -1 << endl;
        return;
    }
    int t = n, tot = 0;
    while (t) {
        v[tot++] = t % 2, t /= 2;
    }
    for (int i = 0; i < tot - 1; i++) {
        if (v[i] & v[i + 1]) {
            cout << -1 << endl;
            return;
        }
    }
    for (int i = 0; i < tot; i++) {
        if (v[i]) {//(n)2=1 0
            a[i] = 1, b[i] = 0;
            a[i - 1] = b[i - 1] = 1;
        }
    }
    int numa = 0, numb = 0;
    for (int i = 0; i < tot; i++) {
        if (a[i]) numa += fac[i];
        if (b[i]) numb += fac[i];
    }
    if ((numa ^ numb) != ((numa & numb) << 1)) {
        cout << -1 << endl;
        return;
    }
    cout << numa << " " << numb << endl;
}


signed main() {
    IOS;
    for (int i = 0, num = 1; i < 32 + 5; i++, num *= 2) fac[i] = num;
    cin >> T;
    while (T--)
        solve();
}
posted @   SxtoxA  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
12 13
点击右上角即可分享
微信分享提示