SMU Summer 2024 Contest Round 6

A Many Formulas

思路:二进制枚举


void solve() {
    string s;
    cin >> s;
    int n = s.size();
    int m = pow(2, n - 1);
    int ans = 0;
    for (int i = 0; i < m; ++i) {
        int now = 0, sum = 0;
        for (int j = 0; j < n; ++j) {
            now = now * 10 + (s[j] - '0');
            if ((i >> j) & 1) {
                sum += now;
                now = 0;
            }
        }
        sum += now;
        ans += sum;
    }
    cout << ans;
}

B Tak and Cards

思路:将数分为大于A和小于A的两部分,只去与A的差值,分别对两部分用背包求和的个数,统计答案即可

void print(__int128 num)
{
    if(num>9)
        print(num/10);
    putchar(num%10+'0');
}
void solve() {
    int n, a;
    cin >> n >> a;
    vector<int> b(n + 1);
    vector<int> x, y;
    __int128 cnt = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> b[i];
        int c = abs(b[i] - a);
        if (b[i] < a) x.push_back(c);
        else if (b[i] > a) y.push_back(c);
        else cnt ++;
    }
    cnt = pow(2, (int)cnt);
    int nx = x.size(), ny = y.size();
    int m = 2500;

    vector<__int128> fx(m + 5);
    vector<__int128> fy(m + 5);
    fx[0] = fy[0] = 1;
    for (int i = 0; i < nx; ++i) {
        for (int j = m; j >= x[i]; --j) {
            fx[j] = fx[j] + fx[j - x[i]];
        }
    }
    for (int i = 0; i < ny; ++i) {
        for (int j = m; j >= y[i]; --j) {
            fy[j] = fy[j] + fy[j - y[i]];
        }
    }
    __int128 ans = 0;
    for (int i = 1; i <= m; ++i) {
        ans += (fx[i] * fy[i] * cnt);
    }
    ans += cnt - 1;
    print(ans);
}

C Wall

思路:floyd求最短路

void solve() {
    int n, m;
    cin >> n >> m;
    vector<vector<int> > g(10, vector<int> (10));
    for (int i = 0; i < 10; ++i) {
        for (int j = 0; j < 10; ++j) {
            cin >> g[i][j];
        }
    }
    for (int k = 0; k < 10; ++k) {
        for (int i = 0; i < 10; ++i) {
            for (int j = 0; j < 10; ++j) {
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
            }
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            int x;
            cin >> x;
            if (x != -1) {
                ans += g[x][1];
            }
        }
    }
    cout << ans;
}

D Coloring Edges on Tree

思路:最大的颜色数为最大度数,首先标记度最大的点的边,bfs继续标记每条表,跳过已经标记过得颜色

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;

struct E {
    int x, y;
};

void solve() {
    int n;
    cin >> n;
    vector<E> g(n - 1);
    vector<int> st(n + 1), d(n + 1);
    vector<vector<int> > ve(n + 1);
    map<PII, int> mp;
    int ma = -1, p;
    for (int i = 0; i < n - 1; ++i) {
        cin >> g[i].x >> g[i].y;
        mp[{g[i].x, g[i].y}] = -1;
        ve[g[i].x].push_back(g[i].y), ve[g[i].y].push_back(g[i].x);
        d[g[i].x] ++, d[g[i].y] ++;
        if (d[g[i].x] > ma) {
            ma = d[g[i].x], p = g[i].x;
        }
        if (d[g[i].y] > ma) {
            ma = d[g[i].y], p = g[i].y;
        }
    }
    vector<int> col(n - 1);
    queue<int> q;
//    cout << p << '\n';
    st[p] = 1e9;
    q.push(p);
    while (q.size()) {
        auto t = q.front();
        q.pop();
        int idx = 1;
        for (auto v:ve[t]) {
            if (st[v]) continue;
            if (idx == st[t]) idx ++;
            mp[{t, v}] = mp[{v, t}] = idx;
            st[v] = idx ++;
            q.push(v);
        }
    }
    cout << ma << '\n';
    for (int i = 0; i < n - 1; ++i) {
        cout << mp[{g[i].x, g[i].y}] << '\n';
    }
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

E Fault-tolerant Network

思路:实际上就是要将a1、an、b1、bn都连上边,求出与它们差最小的数,分别考虑每种连接情况

#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <climits>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0,1, 0, -1};


void solve() {
    int n;
    cin >> n;
    vector<int> a(n + 1), b(n + 1);
    int ans = LLONG_MAX;
    int x1, x2, x3, x4;
    x1 = x2 = x3 = x4 = LLONG_MAX;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    for (int i = 1; i <= n; ++i) {
        cin >> b[i];
        x1 = min(x1, abs(a[1] - b[i]));
        x2 = min(x2, abs(a[n] - b[i]));
    }
    for (int i = 1; i <= n; ++i) {
        x3 = min(x3, abs(b[1] - a[i]));
        x4 = min(x4, abs(b[n] - a[i]));
    }
    ans = min(ans, abs(a[1] - b[1]) + abs(a[n] - b[n]));
    ans = min(ans, abs(a[1] - b[n]) + abs(a[n] - b[1]));
    ans = min(ans, abs(a[1] - b[1]) + x2 + x4);
    ans = min(ans, abs(a[1] - b[n]) + x2 + x3);
    ans = min(ans, abs(a[n] - b[1]) + x1 + x4);
    ans = min(ans, abs(a[n] - b[n]) + x1 + x3);
    ans = min(ans, x1 + x2 + x3 + x4);
    cout << ans << '\n';
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

F Nearest Excluded Points

思路:

点数不多,若距离一个点为1的位置不存在点,说明该位置可以为该点的答案,考虑用已经标记过答案的点去bfs没有标记过的点,更新答案

#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <climits>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0,1, 0, -1};

struct E {
    int x, y;
};
void solve() {
    int n;
    cin >> n;
    vector<E> ve(n + 1), ans(n + 1, {LLONG_MAX, LLONG_MAX});
    map<PII, int> id;
    for (int i = 1; i <= n; ++i) {
        cin >> ve[i].x >> ve[i].y;
        id[{ve[i].x, ve[i].y}] = i;
    }
    queue<E> q;
    for (int i = 1; i <= n; ++i) {
        for (int k = 0; k < 4; ++k) {
            int x = ve[i].x + dx[k], y = ve[i].y + dy[k];
            if (!id.count({x, y})) {
//                cout << ve[i].x << ' ' << ve[i].y << "|" << x << ' ' << y << '\n';
                ans[i] = {x, y};
                q.push({ve[i].x, ve[i].y});
                break;
            }
        }
    }
    while (q.size()) {
        auto [x, y] = q.front();
        q.pop();
        int fa = id[{x, y}];
        int fx = ans[fa].x, fy = ans[fa].y;
        for (int k = 0; k < 4; ++k) {
            int xx = x + dx[k], yy = y + dy[k];
            if (id.count({xx, yy}) && ans[id[{xx, yy}]].x == LLONG_MAX) {
                ans[id[{xx, yy}]] = {fx, fy};
                q.push({xx, yy});
            }
        }
    }
    for (int i = 1; i <= n; ++i) {
        cout << ans[i].x << ' ' << ans[i].y << '\n';
    }
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

G Vacation Query

思路:

线段树维护0和1的最大连续区间长度,若为修改操作,交换0和1维护的线段树即可

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 5e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
#define lc k << 1
#define rc k << 1 | 1
string a;
struct tree {
    int l, r;
    int ans[2], lmx[2], rmx[2];
    int lz;
}tr[N * 4];

void pushup(tree & u, tree ll, tree rr) {
    u.ans[0] = max({ll.ans[0], rr.ans[0], ll.rmx[0] + rr.lmx[0]});
    u.ans[1] = max({ll.ans[1], rr.ans[1], ll.rmx[1] + rr.lmx[1]});

    u.lmx[0] = ll.lmx[0];
    if (ll.lmx[0] == ll.r - ll.l + 1) u.lmx[0] += rr.lmx[0];
    u.lmx[1] = ll.lmx[1];
    if (ll.lmx[1] == ll.r - ll.l + 1) u.lmx[1] += rr.lmx[1];

    u.rmx[0] = rr.rmx[0];
    if (rr.rmx[0] == rr.r - rr.l + 1) u.rmx[0] += ll.rmx[0];
    u.rmx[1] = rr.rmx[1];
    if (rr.rmx[1] == rr.r - rr.l + 1) u.rmx[1] += ll.rmx[1];
}

void build (int k, int l, int r) {
    tr[k] = {l, r};
    if (l == r) {
        if (a[l] == '0') tr[k].rmx[0] = tr[k].lmx[0] = tr[k].ans[0] = 1;
        else tr[k].rmx[1] = tr[k].lmx[1] = tr[k].ans[1] = 1;
        return ;
    }
    int mid = l + r >> 1;
    build (lc, l, mid), build(rc, mid + 1, r);
    pushup(tr[k], tr[lc], tr[rc]);
}

void swap_(int k) {
    swap(tr[k].ans[0], tr[k].ans[1]);
    swap(tr[k].lmx[0], tr[k].lmx[1]);
    swap(tr[k].rmx[0], tr[k].rmx[1]);
}

void pushdown(int k) {
    if (tr[k].lz) {
        swap_(lc), swap_(rc);
        tr[lc].lz ^= 1;
        tr[rc].lz ^= 1;
        tr[k].lz ^= 1;
    }
}

void modify(int k, int l, int r) {
    if (tr[k].l >= l && tr[k].r <= r) {
        swap_(k);
        tr[k].lz ^= 1;
        return ;
    }
    pushdown(k);
    int mid = tr[k].l + tr[k].r >> 1;
    if (l <= mid) modify(lc, l, r);
    if (r > mid) modify(rc, l, r);
    pushup(tr[k], tr[lc], tr[rc]);
}

tree query(int k, int l, int r) {
    if (tr[k].l >= l && tr[k].r <= r) return tr[k];
    pushdown(k);
    int mid = tr[k].l + tr[k].r >> 1;
    if (mid >= r) return query(lc, l, r);
    if (mid < l) return query(rc, l, r);
    tree T;
    pushup(T, query(lc, l, mid), query(rc, mid + 1, r));
    return T;
}

void solve() {
    int n, q;
    cin >> n >> q;
    cin >> a;
    a = ' ' + a;
    build(1, 1, n);
    while (q --) {
        int op, l, r;
        cin >> op >> l >> r;
        if (op == 1) {
            modify(1, l, r);
        } else {
            cout << query(1, l, r).ans[1] << '\n';
        }
    }
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

 

posted @ 2024-07-22 20:36  bible_w  阅读(6)  评论(0编辑  收藏  举报