• 「USACO2011 Nov Gold」解题报告


    「USACO2011 Nov Gold」解题报告

    T1、Above the Median

    题目链接

    (Description)

    给出一个长度为 (n (n leq 10 ^ 5)) 序列 ({ a_n } (a_i leq 10 ^ 9)),问中位数大于等于 (k) 的区间数量。(区间里如果有偶数个数,中位数定义为偏大的那一个)

    (Solution)

    若把 (a_i geq k) 的位置标为 (1)(a_i < k) 标为 (0),并把这个序列记为 (b),该序列前缀和记为 (pre)
    则区间 ([l,r]) 满足题意当且仅当:

    [r - (l - 1) leq 2 imes (pre_r - pre_{l - 1}) ]

    把变量相同的放一边:

    [r - 2 imes pre_r leq (l - 1) - 2 imes pre_{l - 1} ]

    枚举右端点,随便找个数据结构维护左边有几个满足条件的左端点。

    (Source)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    int in() {
        int x = 0; char c = getchar(); bool f = 0;
        while (c < '0' || c > '9')
            f |= c == '-', c = getchar();
        while (c >= '0' && c <= '9')
            x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
        return f ? -x : x;
    }
    template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
    template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
    
    const int N = 1e5 + 5;
    
    int n, nn, k, a[N], pre[N];
    long long res;
    
    struct binary_index_tree {
        int a[N << 1];
        void insert(int p) { for (; p <= nn; p += (p & -p)) ++a[p]; }
        int ask(int p) { int ret = 0; for (; p; p -= (p & -p)) ret += a[p]; return ret; }
    } bit;
    
    int main() {
        //freopen("in", "r", stdin);
        n = in(), k = in(), nn = n + n;
        for (int i = 1; i <= n; ++i)
            a[i] = in();
        for (int i = 1; i <= n; ++i)
            pre[i] = pre[i - 1] + (a[i] >= k);
        bit.insert(n);
        for (int i = 1; i <= n; ++i) {
            res += bit.ask(pre[i] + pre[i] - i + n);
            bit.insert(pre[i] + pre[i] - i + n);
        }
        printf("%lld
    ", res);
        return 0;
    }
    

    T2、Binary Sudoku

    题目链接

    (Description)

    给出一个 (9 imes 9)(01) 矩阵,问最少修改几个数能使每行、每列以及每个九宫格中的异或和为 (0)

    (Solution)

    (f_{k, i, x, y, z}) 表示到第 (k) 行,其中 (1)(k) 行每一列异或和的状态为 (i) (一个二进制数),当前的三个宫格异或和分别是 (x,y,z) 的最少操作次数;
    转移枚举第 (k) 行的操作;
    注意每个九宫格的最后一行 (x,y,z) 都是 (0)

    (Source)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    int in() {
        int x = 0; char c = getchar(); bool f = 0;
        while (c < '0' || c > '9')
            f |= c == '-', c = getchar();
        while (c >= '0' && c <= '9')
            x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
        return f ? -x : x;
    }
    template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
    template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
    
    int a[11][4], b[515][4], f[11][515][2][2][2];
    char str[15];
    
    int main() {
        //freopen("in", "r", stdin);
        for (int i = 1; i <= 9; ++i) {
            scanf(" %s", str + 1);
            for (int j = 1; j <= 9; ++j)
                a[i][0] = (a[i][0] << 1) | (str[j] == '1');
            for (int j = 0; j < 9; ++j)
                a[i][j / 3 + 1] ^= (a[i][0] >> j) & 1;
        }
        for (int i = 1; i < 512; ++i) {
            b[i][0] = b[i - (i & -i)][0] + 1;
            for (int j = 0; j < 9; ++j)
                b[i][j / 3 + 1] ^= (i >> j) & 1;
        }
        memset(f, 0x3f, sizeof(f));
        f[0][0][0][0][0] = 0;
        for (int k = 1, tmp, t1, t2, t3; k <= 9; ++k) {
            if (k % 3 == 0) {
                for (int i = 0; i < 512; ++i)
                    for (int j = 0; j < 512; ++j) {
                        if (b[j ^ a[k][0]][0] & 1)
                            continue;
                        t1 = a[k][1] ^ b[j][1];
                        t2 = a[k][2] ^ b[j][2];
                        t3 = a[k][3] ^ b[j][3];
                        tmp = f[k - 1][i ^ j ^ a[k][0]][t1][t2][t3];
                        chk_min(f[k][i][0][0][0], tmp + b[j][0]);
                    }
            } else {
                for (int i = 0; i < 512; ++i)
                    for (int x = 0; x < 2; ++x)
                        for (int y = 0; y < 2; ++y)
                            for (int z = 0; z < 2; ++z)
                                for (int j = 0; j < 512; ++j) {
                                    if (b[j ^ a[k][0]][0] & 1)
                                        continue;
                                    t1 = x ^ a[k][1] ^ b[j][1];
                                    t2 = y ^ a[k][2] ^ b[j][2];
                                    t3 = z ^ a[k][3] ^ b[j][3];
                                    tmp = f[k - 1][i ^ j ^ a[k][0]][t1][t2][t3];
                                    chk_min(f[k][i][x][y][z], tmp + b[j][0]);
                                }
            }
        }
        printf("%d
    ", f[9][0][0][0][0]);
        return 0;
    }
    

    T3、Cow Steeplechase

    题目链接

    (Description)

    给出 (n (n leq 250)) 平行于坐标轴的线段,选出尽量多的线段使得这些线段两两没有交点 (顶点也算) ,横的与横的,竖的与竖的线段之间保证没有交点,输出最多能选出多少条线段。
    坐标均大于 (0),且不超过 (10 ^ 9)

    (Solution)

    二分图最大独立集。

    (Source)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    int in() {
        int x = 0; char c = getchar(); bool f = 0;
        while (c < '0' || c > '9')
            f |= c == '-', c = getchar();
        while (c >= '0' && c <= '9')
            x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
        return f ? -x : x;
    }
    template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
    template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
    
    const int N = 255;
    
    struct segment {
        int x1, y1, x2, y2;
    } a[N], b[N];
    int n, x, y, mp[N][N], mat[N];
    
    void prep() {
        for (int i = 1; i <= x; ++i)
            if (a[i].x1 > a[i].x2)
                std::swap(a[i].x1, a[i].x2);
        for (int i = 1; i <= y; ++i)
            if (b[i].y1 > b[i].y2)
                std::swap(b[i].y1, b[i].y2);
        for (int i = 1; i <= x; ++i) {
            for (int j = 1; j <= y; ++j) {
                if (b[j].y1 <= a[i].y1 && a[i].y2 <= b[j].y2 &&
                    a[i].x1 <= b[j].x1 && b[j].x2 <= a[i].x2)
                    mp[i][j] = 1;
            }
        }
    }
    
    int vis[N];
    int dfs(const int u, const int tim) {
        if (vis[u] == tim)
            return 0;
        vis[u] = tim;
        for (int v = 1; v <= y; ++v) {
            if (!mp[u][v])
                continue;
            if (!mat[v] || dfs(mat[v], tim)) {
                mat[v] = u;
                return 1;
            }
        }
        return 0;
    }
    int hungary() {
        int ret = 0;
        for (int i = 1; i <= x; ++i)
            ret += dfs(i, i);
        return ret;
    }
    
    int main() {
        //freopen("in", "r", stdin);
        n = in();
        for (int i = 1; i <= n; ++i) {
            a[++x] = (segment){in(), in(), in(), in()};
            if (a[x].x1 == a[x].x2)
                b[++y] = a[x--];
        }
        prep();
        printf("%d
    ", n - hungary());
        return 0;
    }
    
  • 相关阅读:
    web自动化中的三种切换---alert弹框切换
    web自动化中的三种切换--窗口切换
    web自动化中的三种切换---iframe
    web元素定位中的三种等待方法
    web自动化浏览器chrome和驱动chromedriver
    selenium安装
    pytest用例标记规则
    键盘事件
    鼠标事件
    控制浏览器
  • 原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/11649799.html
Copyright © 2020-2023  润新知