zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 090 C D E F

    C - Candies

    题意

    求左上角走到右下角最大的数字和。

    思路

    直接(dp)

    Code

    #include <bits/stdc++.h>
    #define maxn 110
    using namespace std;
    int a[3][maxn], dp[3][maxn];
    typedef long long LL;
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= 2; ++i) {
            for (int j = 1; j <= n; ++j) scanf("%d", &a[i][j]);
        }
        for (int i = 1; i <= n; ++i) dp[1][i] = dp[1][i-1] + a[1][i];
        for (int i = 1; i <= 2; ++i) dp[i][1] = dp[i-1][1] + a[i][1];
        for (int j = 2; j <= n; ++j) {
            dp[2][j] = max(dp[1][j], dp[2][j-1]) + a[2][j];
        }
        printf("%d
    ", dp[2][n]);
        return 0;
    }
    
    

    D - People on a Line

    题意

    给定 (n) 个未知数 (x_1,...x_n)(m) 个等式 (x_{p_i}-x_{q_i}=d_i),问是否可能成立?(即是否存在矛盾)

    思路

    神似 poj 2492 A Bug's Life 二分图染色 || 种类并查集

    对于并查集中的元素,用 (off[ ]) 数组记录它比它的祖先大多少,合并的时候注意一下。
    有条件$$l-fl=off[l] && r-fr=off[r] && r-l=d$$
    于是有

    [off[fr]=fr-fl=d-off[r]+off[l] ]

    Code

    #include <bits/stdc++.h>
    #define maxn 100000
    using namespace std;
    typedef long long LL;
    int fa[maxn], off[maxn];
    int find(int x) {
        if (fa[x] == x) return x;
        int temp = fa[x];
        fa[x] = find(fa[x]);
        off[x] += off[temp];
        return fa[x];
    }
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i) fa[i] = i;
        for (int i = 0; i < m; ++i) {
            int l, r, d;
            scanf("%d%d%d", &l, &r, &d);
            int fl = find(l), fr = find(r);
            if (fl == fr) {
                if (off[r] - off[l] == d) continue;
                else { puts("No"); return 0; }
            }
            else {
                fa[fr] = fl;
                off[fr] = d - off[r] + off[l];
            }
        }
        puts("Yes");
        return 0;
    }
    
    

    E - Avoiding Collision

    题意

    给定一张图,甲乙两人分别从 (s) , (t) 出发,甲要到 (t),乙要到 (s),且两人均走最短路。

    问在途中不相遇的方案数。

    思路

    跑两遍 (dijkstra),跑的时候记录最短路长度(dist[ ])和方案数(way[ ])

    显然,两人不能走同样的路,所以如果没有 在途中不相遇 的条件约束,则答案为 $$ans = ways1[t]*(ways1[t]-1])$$

    然而,题目要求 在途中不相遇,这蕴含了两层含义,在 上不相遇,在 上不相遇。
    // 千万别忘了边Orz

    上不相遇:
    枚举点,判断是否 $$dist1[i]2==dis && dist2[i]2==dis$$

    上不相遇:
    枚举边,判断是否 $$dist1[u] + edge[id].w + dist2[v] == dis && (dist1[u]<<1) < dis && (dist2[v]<<1) < dis$$

    用总答案减去这两部分 (ans - ans1 - ans2) 即为答案

    Code

    #include <bits/stdc++.h>
    #define maxn 100010
    #define maxm 200010
    #define inf 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long LL;
    const LL mod = 1e9 + 7;
    int ne[maxn], tot;
    bool vis[maxn];
    LL dist1[maxn], dist2[maxn], ways1[maxn], ways2[maxn];
    struct Edge { int from, to, ne; LL w; }edge[maxm<<1];
    void add(int u, int v, LL w) {
        edge[tot] = {u, v, ne[u], w};
        ne[u] = tot++;
    }
    struct node {
        int v; LL c;
        bool operator < (const node nd) const { return c > nd.c; }
    };
    int n;
    void dfs(int src, LL* dist, LL* ways) {
        memset(vis, 0, sizeof vis);
        for (int i = 1; i <= n; ++i) dist[i] = inf;
        vis[src] = true; dist[src] = 0; ways[src] = 1;
        priority_queue<node> q;
        while (!q.empty()) q.pop();
        while (true) {
            for (int j = ne[src]; ~j; j = edge[j].ne) {
                int v = edge[j].to;
                if (vis[v]) continue;
                LL now = edge[j].w + dist[src];
                if (now == dist[v]) (ways[v] += ways[src]) %= mod;
                else if (now < dist[v]) {
                    dist[v] = now; ways[v] = ways[src];
                    q.push({v, now});
                }
            }
            while (!q.empty() && vis[q.top().v]) q.pop();
            if (q.empty()) break;
            vis[src = q.top().v] = true;
        }
    }
    int main() {
        memset(ne, -1, sizeof ne);
        int m, s, t;
        scanf("%d%d%d%d", &n,&m,&s,&t);
        for (int i = 0; i < m; ++i) {
            int u, v; LL w;
            scanf("%d%d%lld", &u,&v,&w);
            add(u, v, w), add(v, u, w);
        }
        dfs(s, dist1, ways1);
        dfs(t, dist2, ways2);
        assert(dist1[t] == dist2[s]);
        assert(ways1[t] == ways2[s]);
        LL ww = ways1[t];
        LL ans = ww * (ww-1) % mod;
        LL dis = dist1[t];
        if (!(dis & 1)) {
            LL half = dis >> 1;
            for (int i = 1; i <= n; ++i) if (dist1[i] == half && dist2[i] == half) {
                LL temp = ways1[i] * ways2[i] % mod;
                ans = (ans - (temp * (temp-1)) % mod + mod) % mod;
            }
        }
        for (int i = 0; i < m; ++i) {
            int id = i<<1,
                u = edge[id].from, v = edge[id].to;
            if (dist1[u] > dist1[v]) swap(u, v);
            if (dist1[u] + edge[id].w + dist2[v] == dis && (dist1[u]<<1) < dis && (dist2[v]<<1) < dis) {
                LL temp = ways1[u] * ways2[v] % mod;
                ans = (ans - (temp * (temp-1)) % mod + mod) % mod;
            }
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
    

    F - Number of Digits

    http://www.cnblogs.com/kkkkahlua/p/8400712.html

  • 相关阅读:
    ちょっとした難しい言葉まとめ10
    ちょっとした難しい言葉まとめ9
    ちょっとした難しい言葉まとめ8
    ページの先頭へジャンプするボタンを作るには?
    Interaction with the camera or the photo library
    ナビゲーションバー
    javascript 小计
    爬mei紫图最后代码2015-2019-1-14全部
    备份
    爬mei紫图
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/8372766.html
Copyright © 2011-2022 走看看