【BZOJ】4380: [POI2015]Myjnie
阿新 • • 發佈:2018-12-12
題解
區間dp,先離散化所有價值
\(f[i][j][k]\)表示\([i,j]\)區間裡最小值為\(k\)的價值最大是多少
只考慮\(i <= a <= b <= j\)的區間,列舉中間點\(h\),然後如果這個區間包括h就統計在內
\(f[i][j][k] = max(f[i][h - 1][ >=k] + cost(k) + f[h + 1][j][>=k])\)
構造答案的時候通過記錄每個點前一個轉移點來遞迴即可
程式碼
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 500005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,M; int id[500005],val[4005],tot,ans[55]; int a[4005],b[4005],c[4005],cnt[4005][55]; int f[55][55][4005],g[55][55][4005],pre[55][55][4005]; vector<int> p[55][55]; void dfs(int l,int r,int v,int t = 1) { if(l > r) return; for(int k = t ; k <= tot ; ++k) { if(f[l][r][k] == v) { if(l == r) {ans[l] = val[k];return;} int p = pre[l][r][k]; if(!p) { for(int i = l ; i <= r ; ++i) ans[i] = val[k]; return; } ans[p] = val[k]; dfs(l,p - 1,g[l][p - 1][k],k);dfs(p + 1,r,g[p + 1][r][k],k); return; } } } void Init() { read(N);read(M); for(int i = 1 ; i <= M ; ++i) { read(a[i]);read(b[i]);read(c[i]); val[i] = c[i]; for(int k = 1 ; k <= N ; ++k) { for(int h = k ; h <= N ; ++h) { if(a[i] >= k && b[i] <= h) p[k][h].pb(i); } } } sort(val + 1,val + M + 1); tot = unique(val + 1,val + M + 1) - val - 1; for(int i = 1 ; i <= tot ; ++i) { id[val[i]] = i; } } void Solve() { for(int d = 1 ; d <= N ; ++d) { for(int i = 1 ; i <= N ; ++i) { int j = i + d - 1; if(j > N) break; memset(cnt,0,sizeof(cnt)); int s = p[i][j].size(); for(int k = 0 ; k < s ; ++k) { int t = p[i][j][k]; cnt[id[c[t]]][a[t]]++;cnt[id[c[t]]][b[t] + 1]--; } for(int k = tot ; k >= 1 ; --k) { for(int h = i ; h <= j ; ++h) cnt[k][h] += cnt[k][h - 1]; for(int h = i ; h <= j ; ++h) cnt[k][h] += cnt[k + 1][h]; } for(int k = tot ; k >= 1 ; --k) { for(int h = i ; h <= j ; ++h) { if(f[i][j][k] < cnt[k][h] * val[k] + g[i][h - 1][k] + g[h + 1][j][k]) { pre[i][j][k] = h; f[i][j][k] = cnt[k][h] * val[k] + g[i][h - 1][k] + g[h + 1][j][k]; } } g[i][j][k] = max(g[i][j][k + 1],f[i][j][k]); } } } int r = 0; for(int i = 1 ; i <= tot ; ++i) r = max(r,f[1][N][i]); out(r);enter; dfs(1,N,r); for(int i = 1 ; i <= N ; ++i) { out(ans[i]); i == N ? enter : space; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }