• 自嗨测试赛1


    A Robert 的火车旅行

    题目大意 : 每个点只有一条出边,一共可以走k条边,对于每个点回答有多少个点可以到达自己这个点

    • 不难发现图是一个内向基环树森林,环可以断环成链进行差分,除去环的部分就是树,树上差分就行

    Code

    Show Code
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    const int N = 5e5 + 5;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    struct Edge {
        int n, t;
    }e[N];
    int h[N], edc;
    
    void Add(int x, int y) {
        e[++edc] = (Edge) {h[x], y}; h[x] = edc;
    }
    
    bool v[N];
    int n, k, to[N], stk[N], tp, a[N], cnt, b[N], w[N], s[N*2];
    
    void Dfs(int x, int fa = 0) {
        v[x] = 1;
        stk[++tp] = x; w[x]++;
        if (tp >= k) w[stk[tp-k]]--;
        else s[b[stk[1]]+1]++, s[b[stk[1]]+min(k-tp+1, cnt)]--;
        for (int i = h[x], y; i; i = e[i].n)
            if (!b[y=e[i].t] && y != fa) Dfs(y, x), w[x] += w[y];
        tp--;
    }
    
    int main() {
        freopen("robert.in", "r", stdin);
        freopen("robert.out", "w", stdout);
        n = read(); k = read() + 1;
        for (int i = 1; i <= n; ++i) 
            to[i] = read(), Add(to[i], i);
        for (int j = 1; j <= n; ++j) {
            if (v[j]) continue;
            for (int x = j; !v[a[1] = x]; x = to[x]) v[x] = 1;
            b[a[1]] = ++cnt;
            for (int x = to[a[1]]; x != a[1]; x = to[x])
                b[x] = ++cnt, a[cnt] = x;
            for (int i = 1; i <= cnt; ++i) Dfs(a[i]);
            for (int i = 1; i <= cnt * 2; ++i) s[i] += s[i-1];
            for (int i = 1; i <= cnt; ++i) {
                w[a[i]] += s[i] + s[i+cnt]; 
                s[i] = s[i+cnt] = 0;
                b[a[cnt]] = 0;
            }
            cnt = 0;
        }
        for (int i = 1; i <= n; ++i)
            printf("%d
    ", w[i]);
        return 0;
    }
    

    B 钻石教练老姚的神仙LIS

    题目大意 : 求最长不降子序列,求最多可以同时找出多少个最长不降子序列,求a1,an可以重复选是最多可以同时找出多少个最长不降子序列

    • 数据范围1e3,n2建边跑最大流即可,lis=1是记得特判

    Code

    Show Code
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int N = 1005;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    struct Edge {
        int n, t, f;
    }e[N*N];
    int h[N*2], edc, tmp[N*2];
    
    void Add(int x, int y, int z) {
        e[++edc] = (Edge) {h[x], y, z}; h[x] = edc;
        e[++edc] = (Edge) {h[y], x, 0}; h[y] = edc;
    }
    
    int n, a[N], f[N], lis, q[N*2], dep[N*2], s, t;
    
    bool Bfs() {
        memset(dep + 1, 0, t * 4);
        memcpy(h + 1, tmp + 1, t * 4);
        int l = 1, r = 1; q[1] = s; dep[s] = 1;
        while (l <= r) {
            int x = q[l++];
            for (int i = h[x], y; i; i = e[i].n) {
                if (!e[i].f || dep[y=e[i].t]) continue;
                dep[y] = dep[x] + 1; q[++r] = y;
                if (y == t) return 1;
            }
        }
        return 0;
    }
    
    int Dinic(int x, int lim) {
        if (x == t) return lim;
        int sum = 0;
        for (int i = h[x]; i && lim; i = e[i].n) {
            int y = e[i].t; h[x] = i;
            if (!e[i].f || dep[y] != dep[x] + 1) continue;
            int f = Dinic(y, min(lim, e[i].f));
            lim -= f; sum += f;
            e[i].f -= f; e[i^1].f += f;
        }
        if (!sum) dep[x] = 0;
        return sum;
    }
    
    void Solve(bool g) {
        memset(h + 1, 0, t * 4); edc = 1;
        int ans = 0; s = n * 2 + 1; t = s + 1;
        for (int i = 1; i <= n; ++i) {
            int x = 1;
            if (g && (i == 1 || i == n)) x = 1e3;
            Add(i, i + n, x);
            if (f[i] == 1) Add(s, i, x);
            if (f[i] == lis) Add(i + n, t, x);
            for (int j = 1; j < i; ++j)
                if (a[j] <= a[i] && f[j] + 1 == f[i])
                    Add(j + n, i, 1);
        }
        memcpy(tmp + 1, h + 1, t * 4);
        while (Bfs()) ans += Dinic(s, 1e3);
        printf("%d
    ", ans);
    }
    
    int main() {
        freopen("lis.in", "r", stdin);
        freopen("lis.out", "w", stdout);
        n = read();
        for (int i = 1; i <= n; ++i)
            a[i] = read();
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j < i; ++j)
                if (a[j] <= a[i])
                    f[i] = max(f[i], f[j]);
            lis = max(lis, ++f[i]);
        }
        printf("%d
    ", lis);
        if (lis == 1) printf("%d
    %d
    ", n, n);
        else Solve(0), Solve(1);
        return 0;
    }
    

    C 组合空间

    题目大意 : 给m个子集,问有多少种方案可以组成全集

    • 高维前缀和,子集反演,longdie说是最简单的签到题,改的时候感觉是3个里面最难的。可能是数学太差了吧

    Code

    Show Code
    #include <cstdio>
    
    using namespace std;
    const int N = 1 << 22 | 5, M = 1e9 + 7;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    int n, m, ans, f[N], p[N];
    
    int main() {
        freopen("longdie.in", "r", stdin);
        freopen("longdie.out", "w", stdout);
        m = read(); n = read();
        for (int i = 1; i <= n; ++i) {
            int x = 0;
            for (int k = read(); k; --k)
                x |= 1 << read() - 1;
            f[x ^ (1 << m) - 1]++;
        }
        p[0] = 1;
        for (int i = 1; i <= n; ++i)
            p[i] = 2 * p[i-1] % M;
        for (int i = 1; i <= m; ++i)
            for (int j = 0; j < 1 << m; ++j)
                if (j & 1 << i - 1) (f[j^(1<<i-1)] += f[j]) %= M;
        for (int s = (1 << m) - 1; s >= 0; --s) {
            int cnt = 0, x = p[f[s]] - 1;
            for (int i = s; i; i -= i & -i) cnt++;
            if (cnt & 1) ans = (ans - x + M) % M;
            else ans = (ans + x) % M;
        }
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    服务器RAID5阵列掉了两块盘恢复数据过程
    sql server数据库错误数据恢复过程
    raid崩溃导致存储虚拟化平台数据丢失
    详解MBR分区结构以及GPT分区结构
    存储硬件故障如何恢复数据库
    服务器raid常见故障解决方案
    误删除VMware虚拟机vmdk文件的恢复方法
    HP P2000 服务器数据恢复+服务器数据恢复通用办法
    DELL EqualLogic PS6100存储数据丢失的解决方案
    IBM DS4800服务器RAID信息丢失数据恢复方法
  • 原文地址:https://www.cnblogs.com/shawk/p/14504771.html
Copyright © 2020-2023  润新知