• 2019 Multi-University Training Contest 1


    http://acm.hdu.edu.cn/showproblem.php?pid=6578

    不会做,看题解。

    设dp[i][j][k][l]表示4种颜色出现的最后的位置分别是i,j,k,l的方法数,保证i>=j>=k>=l。其实不取=号,因为同一个位置不能放两个元素,除了开始的若干个比如dp[1][0][0][0]=4。

    合法的转移叠加:
    比如
    刷新的颜色是i:dp[i+1][j][k][l]+=dp[i][j][k][l]
    刷新的颜色是j:dp[i+1][i][k][l]+=dp[i][j][k][l]
    刷新的颜色是k:dp[i+1][i][j][l]+=dp[i][j][k][l]
    刷新的颜色是l:dp[i+1][i][j][k]+=dp[i][j][k][l]

    假如从dp[i][j][k][l]转移到上述状态会导致新状态不满足约束则不进行这次转移,就太麻烦了。
    由于是dp,其实只要遇到约束区间的右端点R的时候再考虑约束就可以了。

    考虑四个数其实是[l,k,j,i],i肯定就是R,要是l>=L则有恰好4种颜色,否则要是k>=L则恰好3种颜色,否则要是j>=L则恰好2种颜色,否则只有1种颜色。

    对每次转移后新状态的i维度必定是i+1,对i维度进行滚动节省空间。复杂度是精确的O(n^4+mn^3),据说很多队觉得过不了。

    还卡memset???15组数据还卡memset?

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    inline int read() {
        int x = 0;
        char c = 0;
        while(c < '0' || c > '9')
            c = getchar();
        while(c >= '0' && c <= '9')
            x = (x << 3) + (x << 1) + c - '0', c = getchar();
        return x;
    }
    
    inline void _write(int x) {
        if(x > 9)
            _write(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline void write(int x) {
        _write(x);
        putchar('
    ');
    }
    
    struct Condition {
        int l, r, x;
        bool operator<(const Condition &c)const {
            return r < c.r;
        }
    } con[105];
    
    const int mod = 998244353;
    int n, m, dp[2][105][105][105], ctop;
    
    inline void clear0(int n) {
        for(int j = 0; j <= n; ++j) {
            for(int k = 0; k <= j; ++k) {
                for(int l = 0; l <= k; ++l) {
                    dp[n & 1][j][k][l] = 0;
                }
            }
        }
    }
    
    inline void clear1(int i, int L) {
        //清除==1种的
        for(int j = L - 1 ; j >= 0; --j) {
            for(int k = j ; k >= 0; --k) {
                for(int l = k ; l >= 0; --l) {
                    dp[i & 1][j][k][l] = 0;
                }
            }
        }
    }
    
    inline void clear2(int i, int L) {
        //清除==2种的
        for(int j = i ; j >= L; --j) {
            for(int k = L - 1; k >= 0; --k) {
                for(int l = k ; l >= 0; --l) {
                    dp[i & 1][j][k][l] = 0;
                }
            }
        }
    }
    
    inline void clear3(int i, int L) {
        //清除==3种的
        for(int j = i ; j >= L ; --j) {
            for(int k = j ; k >= L; --k) {
                for(int l = L - 1; l >= 0; --l) {
                    dp[i & 1][j][k][l] = 0;
                }
            }
        }
    }
    
    inline void clear4(int i, int L) {
        //清除==4种的
        for(int j = i ; j >= L ; --j) {
            for(int k = j ; k >= L ; --k) {
                for(int l = k ; l >= L; --l) {
                    dp[i & 1][j][k][l] = 0;
                }
            }
        }
    }
    
    inline void update1(int i) {
        if(ctop > m || i < con[ctop].r)
            return;
        while(ctop <= m && i == con[ctop].r) {
            //printf("cons %d
    ", ctop);
            int L = con[ctop].l, x = con[ctop].x;
            ++ctop;
            if(x == 1) {
                clear2(i, L);
                clear3(i, L);
                clear4(i, L);
            } else if(x == 2) {
                clear1(i, L);
                clear3(i, L);
                clear4(i, L);
            } else if(x == 3) {
                clear1(i, L);
                clear2(i, L);
                clear4(i, L);
            } else {
                clear1(i, L);
                clear2(i, L);
                clear3(i, L);
            }
        }
    }
    
    inline void update2(int i, int j, int k, int l) {
        dp[(i + 1) & 1][j][k][l] += dp[i & 1][j][k][l];
        if(dp[(i + 1) & 1][j][k][l] >= mod)
            dp[(i + 1) & 1][j][k][l] -= mod;
        dp[(i + 1) & 1][i][k][l] += dp[i & 1][j][k][l];
        if(dp[(i + 1) & 1][i][k][l] >= mod)
            dp[(i + 1) & 1][i][k][l] -= mod;
        dp[(i + 1) & 1][i][j][l] += dp[i & 1][j][k][l];
        if(dp[(i + 1) & 1][i][j][l] >= mod)
            dp[(i + 1) & 1][i][j][l] -= mod;
        dp[(i + 1) & 1][i][j][k] += dp[i & 1][j][k][l];
        if(dp[(i + 1) & 1][i][j][k] >= mod)
            dp[(i + 1) & 1][i][j][k] -= mod;
    }
    
    int solve() {
        ctop = 1;
        memset(dp[1], 0, sizeof(dp[1]));
        dp[1][0][0][0] = 4;
        update1(1);
        for(int i = 1; i <= n - 1; ++i) {
            //printf("i=%d
    ", i);
            clear0(i + 1);
            for(int j = i; j >= 0; --j) {
                for(int k = j ; k >= 0; --k) {
                    if(k == j && k)
                        continue;
                    for(int l = k ; l >= 0; --l) {
                        if(l == k && l)
                            continue;
                        update2(i, j, k, l);
                    }
                }
            }
            update1(i + 1);
            for(int j = i; j >= 0; --j) {
                for(int k = j; k >= 0; --k) {
                    if(k == j && k)
                        continue;
                    for(int l = k ; l >= 0; --l) {
                        if(l == k && l)
                            continue;
                        //printf("dp[%d][%d][%d][%d]=%d
    ", i + 1, j, k, l, dp[(i + 1) & 1][j][k][l]);
                    }
                }
            }
            //printf("
    ");
        }
        int ans = 0;
        for(int j = n - 1; j >= 0; --j) {
            for(int k = j ; k >= 0; --k) {
                for(int l = k ; l >= 0; --l) {
                    ans += dp[n & 1][j][k][l];
                    if(ans >= mod)
                        ans -= mod;
                }
            }
        }
        return ans;
    }
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int T = read();
        while(T--) {
            n = read(), m = read();
            for(int i = 1; i <= m; ++i) {
                con[i].l = read(), con[i].r = read(), con[i].x = read();
            }
            sort(con + 1, con + 1 + m);
            write(solve());
        }
        return 0;
    }
    
  • 相关阅读:
    十一、GUI设计-记事本程序
    十、GUI编程
    OSI七层模型中各层的数据名称
    使用了frame的页面如何整体进行跳转,而不是仅frame跳转
    MySQL脏读、不可重复读、幻读
    博客园后台搜索自己的博客
    完整的ELK+filebeat+kafka笔记
    InnoDB引擎中的索引与算法
    Docker pull下载出现 error pulling image configuration:
    多台服务器通过docker搭建ELK集群
  • 原文地址:https://www.cnblogs.com/Yinku/p/11253382.html
Copyright © 2020-2023  润新知