Codeforces Round #592 (Div. 2)

送分小仙女□ 提交于 2019-12-01 07:43:07

Contest Info


Practice Link

Solved A B C D E F G
6/7 O O Ø Ø Ø - Ø
  • O 在比赛中通过
  • Ø 赛后通过
  • ! 尝试了但是失败了
  • - 没有尝试

Solutions


A. Pens and Pencils

签到。

B. Rooms and Staircases

签到。

C. The Football Season

题意:
给出\(n, p, w, d\),求解:
\[ \begin{eqnarray*} x \cdot w + y \cdot d = p \\ x + y \leq n \end{eqnarray*} \]
题目保证\(d < w\)

思路:
题目保证了\(d < w\),那么有\(y < d\),因为如果\(y = d\),那么相当于\(w * d\),然后取了\(d\)\(w\),那么不如取\(w\)\(d\)更优。
所以直接暴力即可。
也可以直接上\(exgcd\),但是要讨论的东西挺多的。

代码:


view code

#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 1e5 + 10;
ll n, p, w, d, x, y; 
void run() {
    for (ll y = 0; y <= w; ++y) {
        if ((p - y * d) % w == 0) {
            x = (p - y * d) / w;
            if (x >= 0 && y >= 0 && x + y <= n) return pt(x, y, n - x - y);
        }
    }
    pt(-1);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    cout << fixed << setprecision(20);
    while (cin >> n >> p >> w >> d) run();
    return 0;
}

exgcd代码:


view code

import math


def gcd(a, b):
    if b == 0:
        return a
    else:
        return gcd(b, a % b)


def exgcd(a, b, X, Y):
    if a == 0 and b == 0:
        return -1
    if b == 0:
        X[0] = 1
        Y[0] = 0
        return a
    d = exgcd(b, a % b, Y, X)
    Y[0] = Y[0] - a // b * X[0]
    return d

def fceil(x, y):
    return (x + y - 1) // y

def main():
    n, p, w, d = map(int, input().split());
    x = [0]
    y = [0]
    G = gcd(w, d)
    if p % G != 0:
        print(-1)
        return
    if p % w == 0:
        x[0] = p // w
        if x[0] <= n:
            print(x[0], 0, n - x[0])
            return
    if p % d == 0:
        y[0] = p // d
        if y[0] <= n:
            print(0, y[0], n - y[0])
            return
    exgcd(w, d, x, y)
    x[0] = x[0] * p // G
    y[0] = y[0] * p // G
    if x[0] < 0:
        t = fceil(abs(x[0]), d)
        x[0] = x[0] + d * t
        y[0] = y[0] - w * t
    if y[0] < 0:
        t = fceil(abs(y[0]), w)
        x[0] = x[0] - d * t
        y[0] = y[0] + w * t
    if x[0] < 0 or y[0] < 0:
        print(-1)
        return
    t = y[0] // w
    x[0] = x[0] + d * t
    y[0] = y[0] - w * t
    if x[0] + y[0] > n:
        print(-1)
        return
    z = n - x[0] - y[0]
    print(x[0], y[0], z)


main()

D. Paint the Tree

题意:
给出\(n\)个点的树,有三种颜色,要给每个点染色,给出你每个点染某种颜色的代价。
染色方案要满足不存在任意一个三元组\((x, y, z)\)使得\(x, y\)有边相连,\(y, z\)有边相连,并且\(x, y, z\)有任意两个颜色相同。
求合法方案的最小代价。

思路:
考虑只有一条链的时候才存在方案,并且考虑在链上的话,前两个点的颜色确定了,那么整条链的颜色都确定了。
直接暴力枚举然后判断即可。

代码:


view code

#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 1e5 + 10;
int n, d[N], rt, col[N]; ll c[3][N], res, tot; 
vector <vector<int>> G;
void dfs(int u, int fa) {
    for (auto &v : G[u]) if (v != fa) {
        col[v] = 3 - col[u] - col[fa];
        dfs(v, u);
    }
}
ll fee() {
    ll res = 0;
    for (int i = 1; i <= n; ++i)
        res += c[col[i]][i];
    return res;
}
bool ok() {
    for (int i = 1; i <= n; ++i) {
        if (d[i] == 1) rt = i;
        if (d[i] > 2) return false;
    }
    return true;
}
void run() {
    for (int i = 0; i < 3; ++i)
        for (int j = 1; j <= n; ++j)
            cin >> c[i][j];
    memset(d, 0, sizeof d);
    G.clear(); G.resize(n + 1);
    for (int i = 1, u, v; i < n; ++i) {
        cin >> u >> v;
        ++d[u]; ++d[v];
        G[u].push_back(v);
        G[v].push_back(u);
    }
    if (!ok()) return pt(-1);
    int a = 0, b = 0; res = 1e18;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            if (i != j) {
                col[rt] = i;
                col[G[rt][0]] = j;
                dfs(G[rt][0], rt);
                tot = fee(); 
                if (tot < res) {
                    res = tot;
                    a = i, b = j;
                }
            }
        }
    }
    col[rt] = a; col[G[rt][0]] = b;
    dfs(G[rt][0], rt);
    pt(res);
    for (int i = 1; i <= n; ++i)
        cout << col[i] + 1 << " \n"[i == n];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    cout << fixed << setprecision(20);
    while (cin >> n) run();
    return 0;
}

思路二:
考虑\(f[i][j][k]\)表示当前点为\(i\),前一个点的颜色为\(j\),当前点颜色为\(k\)的最小花费,然后转移即可。
但是输出方案要维护一个前驱或者直接确定了最后两个暴力推上去。
但是不能通过判断\(dp\)值来找前驱,这样可能导致染色方案不合法,但是\(dp\)值可能是相同的

E. Minimizing Difference

题意:
给出\(n\)个数\(a_i\),每次可以对一个数增加\(1\)或者减少\(1\)。问操作次数不小于\(k\)的情况下,\(n\)个数中的最大值减最小值的差值最小是多少

思路:
二分答案,然后考虑合法方案一定能让最大值或者最小值固定在某个\(a_i\),然后枚举\(a_i\),算右界范围内的花费是否小于等于\(k\)即可。

代码:


view code

#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 1e5 + 10;
int n; ll a[N], S[N], k; 
ll get(int l, int r) {
    if (l > r) return 0;
    return S[r] - S[l - 1];
}
ll fee(int l, int r) {
    return a[l] * l - get(1, l) + get(r, n) - a[r] * (n - r + 1);
}

bool check(ll x) {
    ll tot = 1e18;
    int pos = 1;
    for (int i = 1; i <= n; ++i) {
        if (pos < i) pos = i;
        while (pos <= n && a[i] + x >= a[pos]) ++pos;
        ll now = a[i] * i - get(1, i) + get(pos, n) - (a[i] + x) * (n - pos + 1);
        chmin(tot, now);
    }
    pos = n;
    for (int i = n; i >= 1; --i) {
        if (pos > n) pos = i;
        while (pos >= 1 && a[i] - x <= a[pos]) --pos;
        ll now = get(i, n) - a[i] * (n - i + 1) - get(1, pos) + (a[i] - x) * pos;
        chmin(tot, now);
    }
    return tot <= k;
}

void run() {
    for (int i = 1; i <= n; ++i) cin >> a[i];
    sort(a + 1, a + 1 + n);
    for (int i = 1; i <= n; ++i) S[i] = S[i - 1] + a[i];
    ll l = 0, r = a[n] - a[1], res = r;
    while (r - l >= 0) {
        ll mid = (l + r) >> 1;
        if (check(mid)) {
            res = mid;
            r = mid - 1;
        } else
            l = mid + 1;
    }
    pt(res);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    cout << fixed << setprecision(20);
    while (cin >> n >> k) run();
    return 0;
}

G. Running in Pairs

题意:
要求构造两个排列\(p, q\),使得\(sum = \sum\limits_{i = 1}^n max(p_i, q_i) \leq k\),并且结果最大。

思路:
考虑将第一个排列顺序排放。
然后考虑第二个排列刚开始也是顺序排放的。
然后考虑交换位置视为元素左移和元素右移。
显然,元素右移不会对答案产生影响。
但是元素左移,左移几个位置它就产生多少贡献。
那么显然可以发现这个变化是连续的,直接贪心即可。

代码:


view code

#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 1e6 + 10;
int n, a[N]; ll k; 
void run() {
    ll base = 1ll * n * (n + 1) / 2;
    if (base > k) return pt(-1);
    for (int i = 1; i <= n; ++i) a[i] = i;
    ll remind = k - 1ll * n * (n + 1) / 2;
    int low = 1;
    for (int i = n; i >= 1 && i > low; --i) {
        if (i - low <= remind) {
            remind -= i - low;
            swap(a[i], a[low]);
            ++low;
        } else {
            swap(a[i], a[i - remind]);
            remind = 0;
            break;
        }
    }
    pt(k - remind);
    for (int i = 1; i <= n; ++i) cout << i << " \n"[i == n];
    for (int i = 1; i <= n; ++i) cout << a[i] << " \n"[i == n];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    cout << fixed << setprecision(20);
    while (cin >> n >> k) run();
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!