1. 程式人生 > >luoguP3255 [JLOI2013]地形生成 動態規劃

luoguP3255 [JLOI2013]地形生成 動態規劃

動態 http col extern n) space gist ret ace

技術分享圖片

出題人語文真好...

各不相同的標號和高度 = 各不相同的標號 + 單獨的高度...

第一問比較簡單,考慮從大到小插入,在相同情況下,按關鍵值從小到大插入

這樣子,關鍵大的元素一定會影響到關鍵小的元素,不會漏統計

插入$i$號元素時,不妨設比它大的數為$S$個,限制為$lim$,和它相同的且已經插入的數有$j$種

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

第二問也比較簡單

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

由於插入的順序是不影響答案的,因此,我們可以限制關鍵值小的必須插在關鍵值後面

轉移時用前綴和轉移就行

我們去掉$O(p)$的勢能需要$O(p^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 = \n) { 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; }

luoguP3255 [JLOI2013]地形生成 動態規劃