zoukankan      html  css  js  c++  java
  • 【YBTOJ】【单调队列】粉刷木板

    粉刷木板

    (N) 块木板从左到右排成一行,有 (m) 个工匠对这些木板进行粉刷,每块木板至多被粉刷一次。

    (i) 个木匠要么不粉刷,要么粉刷包含木板 (S_i) 且长度不超过 (L_i) 的连续的一段木板,每粉刷一块可以得到 (P_i) 的报酬。不同工匠的 (S_i) 不同。 请问如何安排能使工匠们获得的总报酬最多。

    (Nleq 16000 , Mleq 100 , S_ileq 10000)

    题解

    (dp(i,j)) 表示前 (i) 个人涂完 (j) 个木板的最大答案。

    对于第 (i) 个人:

    1. 若他不涂,则 (dp(i,j) = dp(i-1,j)).
    2. 若他不涂当前木板,则 (dp(i,j)=dp(i,j-1)).
    3. 若他涂色,则 (dp(i,j)=max limits_{kin(0,L_i] , jin[S_i,m]}dp(i-1,j-k)+k imes P_i).

    3.修改,为:(dp(i,j)=max limits_{kin[j-L_i.S_i)}dp(i-1,k)+(j-k) imes P_i).

    则:

    [dp(i,j) =maxleft{egin{matrix} dp(i-1,j) \ dp(i,j-1)\ max limits_{kin[j-L_i.S_i)}{dp(i-1,k)+(j-k) imes P_i} end{matrix} ight. ]

    对于以上的第三个式子,我们可以把它移项,变成

    [dp(i,j)= max{j imes P_i+dp(i-1,k)-k imes P_i} , kin[j-L_i,S_i),jge S_i ]

    发现式子后两项与 (j) 无关,可以用单调队列来优化此段最大值。

    复杂度 (O(nm)) .

    代码

    #include <bits/stdc++.h>
    #define fo(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    const int INF = 0x3f3f3f3f,N = 1.6e4+5,M = 105;
    typedef long long ll;
    typedef unsigned long long ull;
    inline ll read(){
    	ll ret=0;char ch=' ',c=getchar();
    	while(!(c>='0'&&c<='9'))ch=c,c=getchar();
    	while(c>='0'&&c<='9')ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
    	return ch=='-'?-ret:ret;
    }
    int n,m;
    struct node{int l,p,s;}a[M];
    inline bool operator < (const node a,const node b){return a.s < b.s;}
    template <typename T> struct dque{
    	T a[N]; int st=1,ed=0;
    	dque(){st=1,ed=0;}
    	inline void clear(){st=1,ed=0;}
    	inline bool empty(){return ed-st+1==0;}
    	inline int size(){return ed-st+1;}
    	inline void push_back(int x){a[++ed] = x;}
    	inline T front(){return a[st];}
    	inline T back(){return a[ed];}
    	inline void pop_back(){ed--;}
    	inline void pop_front(){st++;}
    	T operator [] (int x){return a[st+x-1];}
    };
    dque<int>q;
    int dp[M][N];
    signed main(){
    	n = read() , m = read();
    	for(int i = 1 ; i <= m ; i ++){
    		int l = read() , p = read() , s = read();
    		a[i] = (node){l,p,s};
    	}
    	sort(a+1,a+m+1);
    	for(int i = 1 ; i <= m ; i ++){
    		q.clear();
    		for(int j = max(a[i].s-a[i].l,0) ; j < a[i].s ; j ++){
    			while(!q.empty() && dp[i-1][q.back()] - q.back()*a[i].p < dp[i-1][j] - j*a[i].p)
    				q.pop_back();
    			q.push_back(j);
    		}
    		for(int j = 1 ; j <= n ; j ++){
    			dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
    			if(j >= a[i].s){
    				while(!q.empty() && q.front() + a[i].l < j) q.pop_front();
    				if(!q.empty())dp[i][j] = max(dp[i][j],dp[i-1][q.front()] + (j-q.front())*a[i].p);
    			}
    		}
    	}
    	printf("%d",dp[m][n]);
    }
    
  • 相关阅读:
    skywalking请求头传输协议
    一篇文章带你搞懂SkyWalking调用链追踪框架
    zuihou-admin-cloud很经典的一个微服务开发平台,能够详细的看里面的视频https://www.kancloud.cn/zuihou/zuihou-admin-cloud/1411215
    skywalking权限验证功能
    哔哩哔哩中Openshift红帽培训
    ElasticSearch中文社区视频教程地址
    浅谈一些有趣的区间问题
    浅谈区间最小点覆盖
    洛谷 P1325 雷达安装
    CF12B Correct Solution?
  • 原文地址:https://www.cnblogs.com/Shinomiya/p/15271775.html
Copyright © 2011-2022 走看看