• luoguP3255 [JLOI2013]地形生成 动态规划


    出题人语文真好...

    各不相同的标号和高度 = 各不相同的标号 + 单独的高度...

    第一问比较简单,考虑从大到小插入,在相同情况下,按关键值从小到大插入

    这样子,关键大的元素一定会影响到关键小的元素,不会漏统计

    插入$i$号元素时,不妨设比它大的数为$S$个,限制为$lim$,和它相同的且已经插入的数有$j$种

    那么有$min(S, lim) + j$种插入的方案

    第二问也比较简单

    考虑$dp$,令$f(i, j)$表示在相同的数中,插入到了$i$,并且$i$插入在第$j$段

    由于插入的顺序是不影响答案的,因此,我们可以限制关键值小的必须插在关键值后面

    转移时用前缀和转移就行

    我们去掉$O(p)$的势能需要$O(p^2)$的时间

    而$x_1^2 + x_2^2 ... x_i^2 leqslant (x_1 + x_2 + ... + x_i)^2$

    而序列的势能只有$O(n)$,因此我们的复杂度不会超过$O(n^2)$

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    namespace remoon {
        #define re register
        #define de double
        #define le long double
        #define ri register int
        #define ll long long
        #define sh short
        #define pii pair<int, int>
        #define mp make_pair
        #define pb push_back
        #define tpr template <typename ra>
        #define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++)
        #define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --)    
        extern inline char gc() {
            static char RR[23456], *S = RR + 23333, *T = RR + 23333;
            if(S == T) fread(RR, 1, 23333, stdin), S = RR;
            return *S ++;
        }
        inline int read() {
            int p = 0, w = 1; char c = gc();
            while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
            while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
            
            return p * w;
        }
        int wr[50], rw;
        #define pc(iw) putchar(iw)
        tpr inline void write(ra o, char c = '
    ') {
            if(!o) pc('0');
            if(o < 0) o = -o, pc('-');
            while(o) wr[++ rw] = o % 10, o /= 10;
            while(rw) pc(wr[rw --] + '0');
            pc(c);
        }
        tpr inline void cmin(ra &a, ra b) { if(a > b) a = b; }
        tpr inline void cmax(ra &a, ra b) { if(a < b) a = b; } 
        tpr inline bool ckmin(ra &a, ra b) { return (a > b) ? a = b, 1 : 0; }
        tpr inline bool ckmax(ra &a, ra b) { return (a < b) ? a = b, 1 : 0; }
    }
    using namespace std;
    using namespace remoon;
    
    #define sid 1050
    #define mod 2011
    
    inline void inc(int &a, int b) { a += b; if(a >= mod) a -= mod; }
    inline int mul(int a, int b) { return 1ll * a * b % mod; }
    
    int n;
    struct mountain {
        int h, k;
        friend bool operator < (mountain a, mountain b)
        { return a.h > b.h && (a.h == b.h && a.k < b.k); }
    } mt[sid];
    
    
    int f[1050][1050];
    inline void Solve() {
        int ans = 1;
        for(ri i = 1, j = 1; i <= n; i = j + 1) {
            j = i; while(mt[j].h == mt[j + 1].h) j ++;
            rep(ip, i, j) cmin(mt[ip].k, i);
            rep(ip, 1, mt[i].k) f[i][ip] = 1;
            rep(ip, i, j) {
                if(ip < j) rep(jp, 1, mt[ip + 1].k) inc(f[ip][jp], f[ip][jp - 1]);
                else rep(jp, 1, mt[ip].k) inc(f[ip][jp], f[ip][jp - 1]);
                if(ip < j) rep(jp, 1, mt[ip + 1].k) f[ip + 1][jp] = f[ip][jp];
            }
            ans = mul(ans, f[j][mt[j].k]);
        }
        write(ans);
    }
    
    int main() {
        
        n = read();
        rep(i, 1, n) mt[i].h = read(), mt[i].k = read();
        sort(mt + 1, mt + n + 1);
        
        int ans = 1, num, pre;
        rep(i, 1, n) {
            if(mt[i].h != mt[i - 1].h) pre = i, num = 0;
            else num ++;
            ans = mul(ans, min(pre, mt[i].k) + num);
        }
        write(ans, ' ');
        
        Solve();
        return 0;
    }
  • 相关阅读:
    面向对象编程
    json 和 pickle
    装饰器详解
    内置函数
    Python之基础知识
    Python之路---day2
    用户登录
    Python之路---day1
    js格式化数字和金额
    作用域链–JS基础核心之一
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9781056.html
Copyright © 2020-2023  润新知