[NOIp 2018]all

你。 提交于 2019-11-27 15:38:47

Description

题库链接:

Day1 T1 铺设道路
Day1 T2 货币系统
Day1 T3 赛道修建
Day2 T1 旅行
Day2 T2 填数游戏
Day2 T3 保卫王国

Solution

题解在这儿

Code

Day1 T1 铺设道路

#include <bits/stdc++.h> 
using namespace std;

int n, a, la, ans;

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a);
        if (a > la) ans += a-la;
        la = a;
    }
    printf("%d\n", ans);
    return 0;
}

Day1 T2 货币系统

#include <bits/stdc++.h> 
using namespace std;

int t, n, f[25005], a[105], ma, ans;

void work() {
    memset(f, ma = 0, sizeof(f));
    scanf("%d", &n); ans = n, f[0] = 1;
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), ma = max(a[i], ma);
    for (int i = 1; i <= n; i++)
        for (int j = a[i]; j <= ma; j++)
            if (f[j-a[i]]) f[j]++;
    for (int i = 1; i <= n; i++)
        ans -= f[a[i]] > 1;
    printf("%d\n", ans);
}
int main() {
    scanf("%d", &t);
    while (t--) work();
    return 0;
}

Day1 T3 赛道修建

#include <bits/stdc++.h> 
using namespace std;
const int N = 50000+5, inf = 500000000;

int n, m, u, v, l, cnt, mid, vis[N];
struct tt {int nxt, to, dis; } edge[N<<1];
int path[N], top;
multiset<int> q[N];
multiset<int>::iterator it;

void add(int u, int v, int c) {
    edge[++top] = (tt){path[u], v, c};
    path[u] = top;
}
int dfs(int u, int c) {
    vis[u] = 1;
    if (q[u].size()) q[u].clear();
    for (int i = path[u], l; i; i = edge[i].nxt)
        if (!vis[edge[i].to]) {
            l = dfs(edge[i].to, edge[i].dis);
            if (l >= mid) ++cnt;
            else q[u].insert(l);
        }
    int ans = 0;
    while (!q[u].empty()) {
        it = q[u].lower_bound(mid-(*q[u].begin()));
        if (it == q[u].begin() && q[u].count(*q[u].begin()) == 1) ++it;
        if (it != q[u].end()) ++cnt, q[u].erase(q[u].find(*it));
        else ans = max(ans, *q[u].begin());
        q[u].erase(q[u].find(*q[u].begin()));
    }
    return ans+c;
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i < n; i++) {
        scanf("%d%d%d", &u, &v, &l);
        add(u, v, l), add(v, u, l);
    }
    int ans, R = inf, L = 0;
    while (L <= R) {
        mid = (L+R)>>1;
        cnt = 0;
        for (int i = 1; i <= n; i++) vis[i] = 0;
        if  (dfs(1, 0) >= mid) ++cnt;
        if (cnt >= m) ans = mid, L = mid+1;
        else R = mid-1;
    }
    printf("%d\n", ans);
    return 0;
}

Day2 T1 旅行

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N = 5000+5;

int n, m, a[N], b[N], ku, kv, t, ans[N], kp[N], vis[N];
vector<int> to[N];

void update() {
    if (ans[1] == 0) memcpy(ans, kp, sizeof(ans));
    else for (int i = 1; i <= n; i++)
            if (ans[i] != kp[i]) {
                if (ans[i] > kp[i]) memcpy(ans, kp, sizeof(ans));
                return;
            }
}
bool dfs(int u, int fa) {
    if (vis[u]) return false;
    kp[++t] = u; vis[u] = 1;
    for (int i = 0, sz = to[u].size(), v; i < sz; i++)
        if ((v = to[u][i]) != fa && !(u == ku && v == kv || u == kv && v == ku))
            if (!dfs(v, u)) return false;
    return true;
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &a[i], &b[i]);
        to[a[i]].pb(b[i]), to[b[i]].pb(a[i]);
    }
    for (int i = 1; i <= n; i++) sort(to[i].begin(), to[i].end());
    if (n == m+1) {dfs(1, 0); update(); }
    else for (int i = 1; i <= m; i++) {
        ku = a[i], kv = b[i]; t = 0;
        memset(vis, 0, sizeof(vis));
        if (dfs(1, 0) && t == n) update();
    }
    for (int i = 1; i <= n; i++) printf("%d%c", ans[i], " \n"[i == n]);
    return 0;
}

Day2 T2 填数游戏

#include <bits/stdc++.h>
using namespace std;
const int N = 1000000+15, yzh = 1000000007;

int n, m, ans, s[N], a[N]; 

int main() {
    scanf("%d%d", &n, &m);
    if (n > m) swap(n, m);
    if (n == 1) {
        ans = 1;
        for (int i = 1; i <= m; i++) ans = 2ll*ans%yzh;
    } else if (n == 2) {
        ans = 4;
        for (int i = 1; i < m; i++) ans = 3ll*ans%yzh;
    } else {
        s[n+m] = 1;
        for (int i = n+m-1; i >= 1; i--)
            a[i] = 2+(i <= n)+(i <= m),
            s[i] = 1ll*s[i+1]*a[i]%yzh;
        (ans += 4ll*s[3]%yzh) %= yzh;
        (ans += 4ll*(a[4]+1)*s[5]%yzh) %= yzh;
        for (int i = 4; i <= n; i++) {
            (ans += 2ll*(3+(i <= m))*(a[i+1]+1)*s[i+2]%yzh) %= yzh;
        }
        (ans += 2ll*(a[n+1]+1)*s[n+2]%yzh) %= yzh;
        for (int i = 4; i <= m; i++) {
            (ans += 2ll*(3+(i <= n))*(a[i+1]+1)*s[i+2]%yzh) %= yzh;
        }
        (ans += 2ll*(a[m+1]+1)*s[m+2]%yzh) %= yzh;
    }
    printf("%d\n", ans);
    return 0;
}

Day2 T3 保卫王国

#include <bits/stdc++.h>
#define ll long long
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 100000+5;
const ll inf = 1e10+1;

char rubbish_bin[3];
int n, m, lim, p[N], u, v, path[N], top, x, y, fa[N][20], dep[N];
ll dp[N][2], f[N][20][2][2];
struct tt {
    int to, nxt;    
} edge[N<<1];

void read(int &x) {
    x = 0; char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x<<1)+(x<<3)+ch-48, ch = getchar(); 
}
void add(int u, int v) {
    edge[++top] = (tt){v, path[u]};
    path[u] = top;
}
void dfs(int u, int f, int d) {
    dep[u] = d, fa[u][0] = f, dp[u][1] = p[u];
    for (int i = 1; i <= lim; i++)
        fa[u][i] = fa[fa[u][i-1]][i-1];
    for (int i = path[u], v; i; i = edge[i].nxt)
        if ((v = edge[i].to) != f) {
            dfs(v, u, d+1);
            dp[u][0] += dp[v][1];
            dp[u][1] += min(dp[v][0], dp[v][1]);
        }
}
ll cal(int u, int x, int v, int y) {
    if (dep[u] < dep[v]) swap(u, v), swap(x, y);
    ll u0, u1, v0, v1, t0, t1, l0, l1; int lca;
    if (x) u1 = dp[u][1], u0 = inf;
    else u1 = inf, u0 = dp[u][0];
    if (y) v1 = dp[v][1], v0 = inf;
    else v1 = inf, v0 = dp[v][0];
    for (int i = lim; i >= 0; i--)
        if (dep[fa[u][i]] >= dep[v]) {
            t0 = u0, t1 = u1;
            u0 = min(t0+f[u][i][0][0], t1+f[u][i][1][0]);
            u1 = min(t0+f[u][i][0][1], t1+f[u][i][1][1]);
            u = fa[u][i];
        }
    if (u == v) {
        lca = u;
        if (y) l0 = inf, l1 = u1;
        else l0 = u0, l1 = inf;
    } else {
        for (int i = lim; i >= 0; i--)
            if (fa[u][i] != fa[v][i]) {
                t0 = u0, t1 = u1;
                u0 = min(t0+f[u][i][0][0], t1+f[u][i][1][0]);
                u1 = min(t0+f[u][i][0][1], t1+f[u][i][1][1]);
                t0 = v0, t1 = v1;
                v0 = min(t0+f[v][i][0][0], t1+f[v][i][1][0]);
                v1 = min(t0+f[v][i][0][1], t1+f[v][i][1][1]);
                u = fa[u][i], v = fa[v][i];
            }
        lca = fa[u][0];
        l0 = dp[lca][0]-dp[u][1]-dp[v][1]+u1+v1;
        l1 = dp[lca][1]-min(dp[u][0], dp[u][1])-min(dp[v][0], dp[v][1])+min(u0, u1)+min(v0, v1);
    }
    for (int i = lim; i >= 0; i--)
        if (fa[lca][i]) {
            t0 = l0, t1 = l1;
            l0 = min(t0+f[lca][i][0][0], t1+f[lca][i][1][0]);
            l1 = min(t0+f[lca][i][0][1], t1+f[lca][i][1][1]);
            lca = fa[lca][i];
        }
    if (min(l0, l1) < inf) return min(l0, l1);
    else return -1;
}
int main() {
    read(n), read(m); scanf("%s", rubbish_bin); lim = log(n)/log(2);
    for (int i = 1; i <= n; i++) read(p[i]);
    for (int i = 1; i < n; i++) {
        scanf("%d%d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0, 1);
    for (int u = 1; u <= n; u++) {
        f[u][0][0][0] = inf;
        f[u][0][1][0] = dp[fa[u][0]][0]-dp[u][1];
        f[u][0][0][1] = f[u][0][1][1] = dp[fa[u][0]][1]-min(dp[u][0], dp[u][1]);
    }
    for (int i = 1; i <= lim; i++)
        for (int u = 1; u <= n; u++) {
            int t = fa[u][i-1];
            f[u][i][0][0] = min(f[u][i-1][0][0]+f[t][i-1][0][0], f[u][i-1][0][1]+f[t][i-1][1][0]);
            f[u][i][0][1] = min(f[u][i-1][0][0]+f[t][i-1][0][1], f[u][i-1][0][1]+f[t][i-1][1][1]);
            f[u][i][1][0] = min(f[u][i-1][1][0]+f[t][i-1][0][0], f[u][i-1][1][1]+f[t][i-1][1][0]);
            f[u][i][1][1] = min(f[u][i-1][1][0]+f[t][i-1][0][1], f[u][i-1][1][1]+f[t][i-1][1][1]);
        }
    while (m--) {
        read(u), read(x), read(v), read(y);
        printf("%lld\n", cal(u, x, v, y));
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!