ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #765 (Div. 2)ABCD题解

2022-01-13 15:34:41  阅读:207  来源: 互联网

标签:ABCD const int 题解 Codeforces solve double inline define


A. Ancient Civilization

题意:给定n个数,要求找出一个数y,使得 \(\sum d(x_i, y)\) 最小,其中 \(d(a, b)\) 表示a,b两数的二进制表达式中,不同的位数个数

解法:对每位考虑,如果该位1多,就设为1,否则设为0

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

inline void solve() {
    int n, l; cin >> n >> l;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i ++ ) cin >> a[i];
    int res = 0;
    for (int i = l - 1; ~i; i -- ) {
        int cnt = 0;
        for (int j = 1; j <= n; j ++ ) {
            if (a[j] >> i & 1) cnt ++;
        }
        if (cnt > n - cnt) res |= 1 << i;
    }
    cout << res << endl;
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
    int T; cin >> T;
    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}

B. Elementary Particles

题意:给定一个长度为n的序列,要求找到两个长度为k的连续区间a,b,使得存在一个数i,满足 \(a[i] = b[i]\) 表示的是分别是a,b中的第i个,求k的最大值

解法:贪心

假如我们找到了两个相同的数,设分别在p1, p2,要求框出这段范围,那么这个范围的最大值就是 \(p1 - p2 + n\),所以要让 \(p1 - p2\) 最大,也就是两个要尽量挨得近,存一下相同数的下标, 遍历即可。

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 2e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

vector<int> pos[N];

inline void solve() {
    int n; cin >> n;

    vector<int> a(n + 1), st(N);

    for (int i = 1; i <= n; i ++ ) {
        cin >> a[i];
        st[a[i]] ++;
        pos[a[i]].push_back(i);
    }
    int res = -1;
    for (int i = 1; i <= 150000; i ++ ) {
        if (st[i] >= 2) {
            int mn = -INF;
            for (int j = 0; j < st[i] - 1; j ++ ) mn = max(mn, pos[i][j] - pos[i][j + 1]);
            res = max(res, mn + n);
        }
        pos[i].clear();
    }
    cout << res << endl;
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
    int T; cin >> T;
    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}

C. Road Optimization

题意:从A走到B的路上有n个限速牌,表示你接下来走一公里至少需要的时间,AB间距为 \(l\),现在你最多可以拆掉 \(k\) 个限速牌,使得到达B的时间尽量少,问最少时间。

解法:DP

状态设计:\(dp[i][j]\) 表示到 \(i\) 点时拆了 \(j\) 个限速牌花费的最少时间,其中 \(i\) 点不拆。

状态转移:\(dp[i][j] = min_{p = 0}^{j} (dp[i - p - 1][j - p] + (d[i] - d[i - p - 1]) * a[i - p - 1])\)

看作01背包问题就好理解了

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 510;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

LL dp[N][N];

inline void solve() {
    int n, l, k; cin >> n >> l >> k;
    vector<int> d(n + 2), a(n + 2);
    for (int i = 1; i <= n; i ++ ) cin >> d[i];
    for (int i = 1; i <= n; i ++ ) cin >> a[i];
    d[n + 1] = l;
    memset(dp, 0x3f, sizeof dp);
    dp[1][0] = 0;
    for (int i = 2; i <= n + 1; i ++ ) {
        for (int j = 0; j <= k; j ++ ) {
            dp[i][j] = dp[i - 1][j] + (d[i] - d[i - 1]) * a[i - 1];
            for (int p = 1; p <= j; p ++ ) {
                if (i - p - 1 <= 0) break;
                dp[i][j] = min(dp[i][j], dp[i - p - 1][j - p] + (d[i] - d[i - p - 1]) * a[i - p - 1]);
            }
        }
    }
    LL res = INF;
    for (int i = 0; i <= k; i ++ ) res = min(res, dp[n + 1][i]);
    cout << res << endl;
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
//    int T; cin >> T;
//    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}

D. Binary Spiders

题意:给定n个数和一个数k,要求在n个数中找出一个集合,使得该集合为原数组的子集,且其中的任意两数的异或和至少为k,问最大子集是什么,给出任意一解即可。

解法:Trie

首先要明白,这是位运算,所以我们对每一位分别进行考虑。

我们假设k的最高位1的位置在x(二进制表达中的右边开始数)

在二进制表达式中,我们把每个数的第x及以下的位数抹掉,剩下的数相同的我们叫做同一类书。

首先很显然,不同类的任意两数的异或和一定大于k

其次,同一类的两数中,我们最多可以选2个

假如我们选了两个同一类的数,如果要使得他们的异或和大于等于k,那么必然两数的第x位是不同的

知道了以上后,可以用抽屉原理来解释,如果选了三个的话,那么必定存在任意两个同一类的数,使得第x位相同,从而异或和小于k

那么就简单了,首先对所有数分类,这一步用哈希下即可

然后对同一类中,利用trie找找看是否能有两个数的异或和大于等于k即可,有就选上,没有就随便选一个

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 3e5 + 10, M = N * 30;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

int tr[M][2], num;
int ed[M];
int n, k;
vector<int> ans;

void init() {
    for (int i = 0; i <= num; i ++ ) {
        tr[i][0] = tr[i][1] = ed[i] = 0;
    }
    num = 0;
}

void Insert(int x, int idx) {
    int p = 0;
    for (int i = 30; ~i; i -- ) {
        int c = x >> i & 1;
        if (!tr[p][c]) tr[p][c] = ++ num;
        p = tr[p][c];
    }
    ed[p] = idx;
}

int Find(int x) {
    int p = 0, sum = 0;
    for (int i = 30; ~i; i -- ) {
        int c = x >> i & 1;
        if (tr[p][c ^ 1]) {
            p = tr[p][c ^ 1];
            sum |= (c ^ 1) * (1 << i);
        } else {
            p = tr[p][c];
            sum |= c * (1 << i);
        }
    }
    sum = sum ^ x;
    if (sum >= k) return ed[p];
    else return -1;
}

inline void solve() {
    cin >> n >> k;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i ++ ) cin >> a[i];
    int p = 0;
    for (int i = 30; ~i; i -- ) {
        if (k >> i & 1) {
            p = i;
            break;
        }
    }
    int base = (1 << 30) - (1 << (p + 1));
    if (k == 0) {
        cout << n << endl;
        for (int i = 1; i <= n; i ++ ) cout << i << ' ';
        cout << endl;
        return ;
    }
    unordered_map<int, vector<PII>> f;
    for (int i = 1; i <= n; i ++ ) {
        int now = a[i] & base;
        f[now].emplace_back(a[i], i);
    }
    for (auto ite : f) {
        init();
        for (auto i2 : ite.second) Insert(i2.first, i2.second);
        bool is = false;
        for (auto i2 : ite.second) {
            int idx = i2.second;
            int tmp = Find(a[idx]);
            if (tmp != -1) {
                ans.push_back(tmp);
                ans.push_back(idx);
                is = true;
                break;
            }
        }
        if (!is) ans.push_back(ite.second[0].second);
    }
    if (ans.size() <= 1) cout << -1 << endl;
    else {
        cout << ans.size() << endl;
        for (auto ite : ans) cout << ite << ' ';
        cout << endl;
    }
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
//    int T; cin >> T;
//    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}

标签:ABCD,const,int,题解,Codeforces,solve,double,inline,define
来源: https://www.cnblogs.com/JYF-AC/p/15797857.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有