zoukankan      html  css  js  c++  java
  • 2020 ccpc 威海

    2020 ccpc 威海

    G Caesar Cipher

    题意:

    给你n个数, 你有两种操作

    1.将区间 ([l, r])的数加1, 同时在模上65536

    2.询问 ([l, l + x], [r, r + x]) 问这两段区间是否一样

    判断两个区间是否一样?很容易想到哈希, 对于操作如果直接取模那么就很有可能出现hash冲突, 但是如果维护一个最大值, 然后暴力修改, 然后hash值取模改成1e9 + 7就可以a了

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N = 5e5 + 100;
    
    struct segment {
        ll sum, ha, maxn;
    }tree[40 * N];
    
    ll fn[N], a[N], flag[40 * N];
    const ll mod = 1e9 + 7;
    
    #define m (l + r) / 2
    #define lson 2 * node
    #define rson 2 * node + 1
    
    void build(int l, int r, int node) {
        if (l == r) {
            tree[node].sum = fn[l];
            tree[node].ha = fn[l] * a[l];
            tree[node].maxn = a[l];
            return;
        }
        build(l, m, lson);
        build(m + 1, r, rson);
        tree[node].sum = tree[lson].sum + tree[rson].sum;
        tree[node].maxn = max(tree[lson].maxn, tree[rson].maxn);
        tree[node].ha = (tree[lson].ha + tree[rson].ha) % mod;
    }
    
    void push_down(int node) {
        if (flag[node]) {
            tree[lson].maxn += flag[node];
            tree[rson].maxn += flag[node];
            tree[lson].ha = (tree[lson].ha + (flag[node] % mod * tree[lson].sum % mod) % mod) % mod;
            tree[rson].ha = (tree[rson].ha + (flag[node] % mod * tree[rson].sum % mod) % mod) % mod;
            flag[lson] += flag[node];
            flag[rson] += flag[node];
            flag[node] = 0; 
        }
    }
    
    void work(int l, int r, int node) {
    
        if (l == r) {
            tree[node].maxn = tree[node].maxn % 65536;
            tree[node].ha = tree[node].maxn * tree[node].sum % mod;
            return;
        }  
        push_down(node);
        if (tree[lson].maxn >= 65536) {
            work(l, m, lson);
        }
    
        if (tree[rson].maxn >= 65536) {
            work(m + 1, r, rson);
        }
        tree[node].maxn = max(tree[lson].maxn, tree[rson].maxn);
        tree[node].ha = (tree[lson].ha + tree[rson].ha) % mod;
    }
    
    void update(int ql, int qr, int l, int r, int node) {
        if (ql <= l && qr >= r) {
            tree[node].maxn++;
            tree[node].ha = (tree[node].ha + tree[node].sum) % mod; 
            flag[node]++;
    
            if (tree[node].maxn >= 65536) {
                push_down(node);
                work(l, r, node);
            }
            return;
        }
        push_down(node);
        if (ql <= m) update(ql, qr, l, m, lson);
        if (qr > m) update(ql, qr, m + 1, r, rson);
        tree[node].maxn = max(tree[lson].maxn, tree[rson].maxn);
        tree[node].ha = (tree[lson].ha + tree[rson].ha) % mod;
    }
    
    ll query(int ql, int qr, int l, int r, int node) {
        if (ql <= l && qr >= r) {
            return tree[node].ha;
        }
        ll ans = 0;
        push_down(node);
        if (ql <= m) ans = (ans + query(ql, qr, l, m, lson)) % mod;
        if (qr > m) ans = (ans + query(ql, qr, m + 1, r, rson)) % mod;
        return ans;
    }
    
    
    int main() {
        int n, q;
        scanf("%d %d", &n, &q);
        for (int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
        }
        fn[1] = 1; 
        for (int i = 2; i <= n + 10; i++) {
            fn[i] = fn[i - 1] * 27;
            fn[i] %= mod;
        }
    
        build(1, n, 1);
        while (q--) {
            int op, l, r;
            scanf("%d %d %d", &op, &l, &r);
            if (op == 1) {
                update(l, r, 1, n, 1);
            } else {
                int x; scanf("%d", &x);
                ll ha = query(l, l + x - 1, 1, n, 1);
                ll ha1 = query(r, r + x - 1, 1, n, 1);
                if (l > r) {
                    int len = l - r;
                    ha1 = ha1 * fn[len + 1] % mod;
                } else {
                    int len = r - l;
                    ha = ha * fn[len + 1] % mod;
                }
                if (ha == ha1) {
                    puts("yes");
                } else {
                    puts("no");
                }
            }
        }
    }
    

    C Rencontre

    题意:

    给你一颗树, 然后有三个人每个选择m个点最后问这三个到达某个点最短的期望是多少?

    题解:

    这题有个东西要知道, 假设树上有三个点 (a,b, c)那么这三个点到某点的最近距离是 (frac{1}{2}(dist(a, b) + dist(b, c) + dist(a, c))) 如果你知道这个公式那么答案不就是求

    (ans = frac{sum_{iin{a}} sum_{jin{b}} sum_{zin{c}} dist(i, j) + dist(j, z)+ dist(i, z)}{2})

    最后的期望就等于 (frac{ans}{cnta * cntb * cntc})(cnta)表示a的数量)

    等于上面的公式可以在继续化简得到

    ((sum_{iin{a}} sum_{jin{c}} dist(i, j) ) * cntc + (sum_{iin{a}} sum_{jin c} dist(i, j)) * cntb + (sum_{iin{b}} sum_{jin{c}} dist(i, j) ) * cnta)

    知道这个公式后就可以用dp求出 所有a到b的距离和, 所有a到c的距离和, 所有b到c的距离后。

    注意爆long long

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    const int N = 2e5 + 7;
    
    ll dp[N][3], sz[N][3];
    
    int head[N], top = 1, n, a[N], b[N], c[N], visa[N], visb[N], visc[N];
    
    struct edge {
        int to, w, nxt;
    }e[2 * N];
    
    void add_edge(int u, int v, int w) {
        e[top].to = v;
        e[top].w = w;
        e[top].nxt = head[u];
        head[u] = top++;
    }
    
    
    __int128 ab = 0, ac = 0, bc = 0;
    ll ma, mb, mc, sum;
    
    void dfs(int u, int fa) {
        if (visa[u]) {
            sz[u][0] = 1;
        } 
        if (visb[u]) {
            sz[u][1] = 1;
        }
        if (visc[u]) {
            sz[u][2] = 1;
        }
        for (int i = head[u]; i; i = e[i].nxt) {
            int to = e[i].to;
            int w = e[i].w;
            if (to == fa) {
                continue;
            }
            dfs(to, u);       
            dp[u][0] += dp[to][0] + sz[to][0] * 1ll * w;
            dp[u][1] += dp[to][1] + sz[to][1] * 1ll * w;
            dp[u][2] += dp[to][2] + sz[to][2] * 1ll * w;
    
            sz[u][0] += sz[to][0];
            sz[u][1] += sz[to][1];
            sz[u][2] += sz[to][2];
            
        }
    }
    
    ll fn[N][3], fz[N][3];
    
    void dfs1(int u, int fa) {
    
        if (visa[u]) {
            ac += fn[u][2];
            ab += fn[u][1]; 
            
        }
        if (visb[u]) {
            bc += fn[u][2];
            
        }
       
    
        
        for (int i = head[u]; i; i = e[i].nxt) {
            int to = e[i].to;
            int w = e[i].w;
            if (to == fa) continue;
            
            ll sb = fn[u][1] - dp[to][1] - 1ll* w * sz[to][1];
            sb = sb + w * (mb - sz[to][1]);
            fn[to][1] = sb  + dp[to][1];
    
            ll sc = fn[u][2] - dp[to][2] - 1ll * w * sz[to][2];
            sc = sc + w * (mc - sz[to][2]);
            fn[to][2] = sc + dp[to][2];
       
            dfs1(to, u); 
    
        }
    
    }
    
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i < n; i++) {
            int u, v, w;
            scanf("%d %d %d", &u, &v, &w);
            add_edge(u, v, w);
            add_edge(v, u, w);
        }
    
        scanf("%d", &ma);
        for (int i = 1; i <= ma; i++) {
            scanf("%d", &a[i]);
            visa[a[i]] = 1;
        }
    
        scanf("%d", &mb);
        for (int i = 1; i <= mb; i++) {
            scanf("%d", &b[i]);
            visb[b[i]] = 1;
        }
    
        scanf("%d", &mc);
        for (int i = 1; i <= mc; i++) {
            scanf("%d", &c[i]);
            visc[c[i]] = 1;
        }
        sum = ma * mb * mc;
    
        dfs(1, 0);
        fn[1][0] = dp[1][0];
        fn[1][1] = dp[1][1];
        fn[1][2] = dp[1][2];
    
        dfs1(1, 0);
     
        __int128 ans = ac * mb + bc * ma + ab * mc;
        ans = ans / 2;
        double res = (double)ans / (double)sum;
    
        printf("%.9f
    ", res);
    
    
    
    
    
    
    }
    
  • 相关阅读:
    ROS学习笔记六:xxx.launch文件详解
    XML 基础学习
    Qt之界面(自定义标题栏、无边框、可移动、缩放)
    (转)YV12 and NV12
    FFMPEG的解码后的数据格式
    (转)使用AfxGetMainWnd函数的一个心得
    mout系统流程
    关于多画面窗口切换的刷新重绘问题
    (转)Invalidate、RedrawWindow与UpdateWindow的区别
    (转)关于三星cortex A9 Sate4412 开发板 uboot 启动的一些问题释疑
  • 原文地址:https://www.cnblogs.com/BOZHAO/p/13924817.html
Copyright © 2011-2022 走看看