zoukankan      html  css  js  c++  java
  • CF339

    C. Xenia and Weights

    有1...10k的砝码,在天枰上,左右轮流放置砝码,要求之后左右轮流比另一侧重量要大,要求相邻两次砝码不能相同。

    解题报告给出(i,j,k)表示balance,j表示最后一次的砝码重量,k表示第几步,然后表示从点(0,0,0)->(x,y,m)的图论问题,跟动态规划是等价的,复杂度是O(w^3*m)。

    我给出了一个比上述算法更优的一个算法,做法是用dp[i][j]表示第i步balance达到j时的所有可能的砝码情况的二进制mask,复杂度是O(w^2*m),但要求w<32。

    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int dp[1005][25];
    char w[15];
    
    int main() {
        int m;
        scanf("%s%d", w, &m);
    
        memset(dp, 0, sizeof(dp));
        dp[0][10] = 1;
    
        for (int i = 1; i <= m; i++) {
            for (int j = 0; j <= 20; j++) {
                if (dp[i - 1][j] > 0) {
                    for (int k = 1; k <= 10; k++) if (w[k - 1] == '1') {
                        if (dp[i - 1][j] ^ (1 << k)) {
                            if (j >= 10 && j - k < 10) {
                                dp[i][j - k] |= (1 << k);
                            } else if (j < 10 && j + k > 10) {
                                dp[i][j + k] |= (1 << k);
                            } 
                        }
                    }
                }
            } 
        }
    
        int ans_j = -1;
        for (int j = 0; j <= 20; j++) if (dp[m][j] > 0)
            ans_j = j;
    
        if (ans_j == -1) {
            printf("NO
    ");
        } else {
            printf("YES
    "); 
            int i = m;
            vector<int> ans;
            int last = 0;
            while (i > 0) {
                for (int j = 1; j <= 10; j++) {
                    if (dp[i][ans_j] & (1 << j)) {
                        if (j == last) continue;
    
                        ans.push_back(j);
                        
                        if (ans_j >= 10) ans_j -= j;
                        else ans_j += j;
    
                        last = j;
    
                        break;
                    }
                }
                i--;
            }
            for (i = ans.size() - 1; i >= 0; i--) {
                printf("%d ", ans[i]);
            }
            printf("
    ");
        }
    }

    D. Xenia and Bit Operations

    很裸的一个线段树了。

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int MAXN = 1 << 17;
    
    int num[MAXN];
    
    class SegNode {
    public:
        int L, R;
        int level, sum;
    } node[MAXN * 4];
    
    class SegTree {
    public:
        void build(int r, int L, int R) {
            node[r].L = L;
            node[r].R = R;
    
            if (L == R) {
                // leaf
                node[r].level = 0;
                node[r].sum = num[L];
            } else {
                // non leaf 
                int M = (L + R) / 2;
                build(2 * r, L, M);
                build(2 * r + 1, M + 1, R);
                node[r].level = node[2 * r].level + 1;
                if (node[r].level & 1) {
                    node[r].sum = node[2 * r].sum | node[2 * r + 1].sum;
                } else {
                    node[r].sum = node[2 * r].sum ^ node[2 * r + 1].sum;
                }
            }
        }
        void update(int r, int p, int b) {
            if (node[r].L == node[r].R) {
                node[r].sum = b; 
            } else {
                if (p <= node[2 * r].R) {
                    // left
                    update(2 * r, p, b);
                } else if (p >= node[2 * r + 1].L) {
                    // right 
                    update(2 * r + 1, p, b);
                }
                if (node[r].level & 1) {
                    node[r].sum = node[2 * r].sum | node[2 * r + 1].sum;
                } else {
                    node[r].sum = node[2 * r].sum ^ node[2 * r + 1].sum;
                }
            } 
        }
    } tree;
    
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= (1 << n); i++) {
            scanf("%d", &num[i]);
        }
        tree.build(1, 1, 1 << n);
        for (int i = 0; i < m; i++) {
            int p, b;
            scanf("%d%d", &p, &b);
            tree.update(1, p, b);
            printf("%d
    ", node[1].sum);
        }
    }
  • 相关阅读:
    DMA详解
    Python实现爬虫设置代理IP和伪装成浏览器的方法(转载)
    Python3 简单验证码识别思路及实例
    Python3 比较两个图片是否类似或相同
    python3 验证码图片切割
    python3 验证码去噪
    Python3 OpenCV应用
    python3 IEDriver抓取时报数据
    Impala 数值函数大全(转载)
    java 获取指定日前的前一天
  • 原文地址:https://www.cnblogs.com/litstrong/p/3285099.html
Copyright © 2011-2022 走看看