• [CF1076F] Summer Practice Report


    Description

    Transmission Gate

    Solution

    这一题可以考虑Dp,设(Dp[i][j]) 为在第i段中,以j颜色为结尾的最后一小段长度的最小值。

    那么可以先考虑以表为结尾的情况:

    1. 表上一个线段的结尾,就把表看作分隔符,那么分隔符的数量下界是$lowerBound = lceil frac{(Dp[i - 1][j] + a[i])}{k} ceil - 1 (, 如果`b[i] > cnt`, 那么)dp[i][j] = 1(,上界)upperBound$是a[i] * k

    2. 表是上一个线段的结尾, 分隔符数量下界是(lowerBound = lceil frac{a[i]}{k} ceil - 1), 上界 $upperBound $ 是 (a[i] * k + (k - Dp[i - 1][j ~ xor ~ 1]))

      最后判断(dp[n][0] leq k || dp[n][1] leq k)

    Summary

    ​ 刚开始设状态(dp[i][j][l]) 表示dp到ith段,段的最后颜色为j,这样的颜色在这一段的最后一部分有l长是否有解。 其实这样是不对的,算方案数判断是否可行的套路只适用于一些容斥数学题(eg. Mobius), 所以就多上一维的冗余信息。

    ​ 问题的模型是: 我们有n个段,段之间首尾相连,要求段中间的连续的隔板与球不超过k个。求是否有解。这样,我们不关心内部的排列方式, 并且内部排列不同不会影响下一段。这样的话我们可以直接考虑外部限制的情况下,钦定一种内部可行的方式。 而钦定就是对简单贪心的考察。

    ​ 因为上一段的影响对下一段越小,对解的限制也就越小(越容易出解),所以可以直接贪心。

    ​ 先考虑公式,将无关的公式看做挡板,表看作球。然后直接尽量容纳表即可。

    Code

    #include<bits/stdc++.h>
    using std :: min;
    #define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    #define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
    #define clar(a, b) memset((a), (b), sizeof(a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    typedef long long LL;
    typedef long double LD;
    int read() {
        char ch = getchar();
        int x = 0, flag = 1;
        for (;!isdigit(ch); ch = getchar()) if (ch == '-') flag *= -1;
        for (;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        return x * flag;
    }
    void write(int x) {
        if (x < 0) putchar('-'), x = -x;
        if (x >= 10) write(x / 10);
        putchar(x % 10 + 48);
    }
    
    const int Maxn = 3e5 + 9;
    static int dp[Maxn][2], n;
    static int x[Maxn], y[Maxn], k;
    
    void init() {
        n = read(), k = read();
        rep (i, 1, n) x[i] = read();
        rep (i, 1, n) y[i] = read();
    }
    
    int getCalc(int preVal, int preSeparator, int nowVal, int nowSeparator) {
        int res = 0x3f3f3f3f;
        if (preVal < 0x3f3f3f3f) {
                LL lowerBound = ceil((1ll * preVal + nowVal) * 1. / k) - 1;
                if (nowSeparator < lowerBound) res = min(res, 0x3f3f3f3f);
                else if (nowSeparator > 1ll * nowVal * k) res = min(res, 0x3f3f3f3f);
                else if (nowSeparator > lowerBound) res = min(res, 1);
                else res = min(1ll * res, (1ll * preVal + nowVal) % k ? (1ll * preVal + nowVal) % k : k);
        }
    
    	if (preSeparator < 0x3f3f3f3f) {
    		LL lowerBound = ceil(nowVal * 1. / k) - 1;
                if (nowSeparator < lowerBound) res = min(res, 0x3f3f3f3f);
                else if (nowSeparator > 1ll * (nowVal - 1) * k + (k - preSeparator)) res = min(res, 0x3f3f3f3f);
                else if (nowSeparator > lowerBound) res = min(res, 1);
                else res = min(1ll * res, (1ll * nowVal) % k ? (1ll * nowVal) % k : k);
    	}
        return res;
    }
    
    void solve() {
        dp[0][0] = 0; dp[0][1] = 0;
    
        rep (i, 1, n) {
            dp[i][0] = getCalc(dp[i - 1][0], dp[i - 1][1], x[i], y[i]);
            dp[i][1] = getCalc(dp[i - 1][1], dp[i - 1][0], y[i], x[i]);
        }
    
        puts(dp[n][0] <= k || dp[n][1] <= k ? "YES" : "NO");
    }
    
    int main() {
    
        init();
        solve();
    
    #ifdef Qrsikno
        debug("
    Running time: %.3lf(s)
    ", clock() * 1.0 / CLOCKS_PER_SEC);
    #endif
        return 0;
    }
    
  • 相关阅读:
    Jenkins历史构建作业jobs的删除与管理
    Redis消息队列与主流的消息队列中间件对比
    GDAL数据模型
    Android的语言切换
    GDAL驱动实现向导
    Win7 安装IIS
    局域网中其他机器不能访问本机IIS网站
    DXF库(dxflib)使用指南
    GDAL中文学习资料
    QT的中文站址
  • 原文地址:https://www.cnblogs.com/qrsikno/p/10003676.html
Copyright © 2020-2023  润新知