• Fence


    Fence

    有一个长度为n的([1,n])墙,有k位工人,第i位工人有参数(s_i,p_i,l_i),意思该位工人可以刷包含(s_i)的长度小于等于(l_i)的区间,报酬为区间长度乘以(p_i),墙的一个位置不能被重复刷,问最大的报酬之和,(1 <= n <= 16 000,1 <= k <= 100)

    注意到k * n才十万,不难想到设(f[i][j])表示前i位工人刷前j个位置的最大报酬之和,注意到我们要保证递推的无后效性,于是我们得把工人的(s_i)排序,因此有

    [f[i][j]=max(f[i-1][j],f[i][j-1],max_{j-l_ileq kleq s_i}f[i-1][k]+(j-k) imes p_i) ]

    注意到在i一定时,决策范围都是呈单调性,且j与k无关,于是可以使用单调队列优化,注意判边界即可,时间复杂度(O(nk))

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define il inline
    #define ri register
    using namespace std;
    struct inter{
    	int l,p,s;
    	il bool operator<(const inter&x)const{
    		return s<x.s;
    	}
    }I[150];
    int dp[150][16050],T[20050],L,R;
    il void read(int&);
    template<class free>
    il free Max(free,free);
    int main(){
    	int N,K;
    	read(N),read(K);
    	for(int i(1);i<=K;++i)
    		read(I[i].l),read(I[i].p),read(I[i].s);
    	sort(I+1,I+K+1);
    	for(int i(1),j;i<=K;++i){
    		L=1,R=0;
    		for(j=0;j<=N;++j){
    			while(L<=R&&T[L]<j-I[i].l)++L;
    			dp[i][j]=Max(dp[i][j-1],dp[i-1][j]);//麻烦解释一下,这里明显越界了,但是改成不越界反而a不掉了
    			if(L<=R&&j>=I[i].s)dp[i][j]=Max(dp[i][j],dp[i-1][T[L]]+(j-T[L])*I[i].p);
    			if(j<I[i].s){
    				while(L<=R&&dp[i-1][j]-j*I[i].p>=dp[i-1][T[R]]-T[R]*I[i].p)--R;
    				T[++R]=j;
    			}
    		}
    	}printf("%d",dp[K][N]);
    	return 0;
    }
    template<class free>
    il free Max(free a,free b){
    	return a>b?a:b;
    }
    il void read(int &x){
    	x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
    	while(c>='0'&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
    
  • 相关阅读:
    WPS JS宏
    WPS基础
    算法文章收藏
    辩论赛
    物流系统
    C#导出excel复杂表格(单元各合并)
    VUE复杂表格合并
    Linux系统创建一个npm命令行工具
    Java使用技巧记录
    Ubuntu系统安装nodejs及npm
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10961964.html
Copyright © 2020-2023  润新知