• 【BZOJ】4380: [POI2015]Myjnie


    题解

    区间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('
    ')
    #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;
    }
    
  • 相关阅读:
    gobject对象不宜作为动态加载的插件
    用内存管理器的钩子函数跟踪内存泄漏
    DBUS与多线程
    broncho小组放假半天为中国奥运加油
    多进程DirectFB用X11显示的死锁问题
    佛诞节快乐
    R语言中substr函数,字符串截取函数
    R语言中while循环
    R语言中求分位数
    R语言中利用sapply函数提取列表中元素
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10108100.html
Copyright © 2020-2023  润新知