题意:n个墙壁m个粉刷匠,每个墙壁至多能被刷一次,每个粉刷匠要么不刷,要么就粉刷包含第Si块的长度不超过Li的连续墙壁(中间可不刷),每一块被刷的墙壁都可获得Pi的利润,求最大利润

避免重复粉刷:

首先对Si排序并定义\(f[i][j]\):前i个木匠处理到第j块木板时的最大利润

此时[j+1,n]保证没被处理以满足无后效性

保证情况一的合法

\(f[i][j]=f[i-1][j]\)

保证情况二的Si必须被粉刷

定义处理的区间为[k+1,j]

则\(f[i][j]=max_kf[i-1][k]+P_i*(j-k)\)

此时要求Si必须在[k+1,j]内部,则对k加以限定:\(k+1≤S_i≤j\)

连续长度的表示:\(j-k≤L_i\)

中间可空出部分的表示\(f[i][j]=f[i][j-1]\)

由此可总结转移方程的三部分

前两部分为 \(f[i][j]=max(f[i-1][j],f[i][j-1])\)

最后一部分为\(f[i][j]=max_{j-L_i≤k≤S_i-1}f[i-1][k]+P_i*(j-k),S_i≤j\)

对于第三部分可改写方程为\(f[i][j]=max_{j-L_i≤k≤S_i-1}(f[i-1][k]-k*P_i)+j*P_i,S_i≤j\)以满足单调队列优化

单调队列在\(i\)的内循环当中可认为\(i\)是常数,也就是说每一层\(i\)都需要设立一个只与\(k\)有关的单调队列\(que\),但在实际中只使用一个

\(que\)每一次的初始化范围由最小的\(j\)决定

由\(S_i≤j\)和\(j-L_i≤k≤S_i-1\)

得\(S_i-L_i≤k_{init}≤S_i-1\)

此时\(j=1\)则得到所有有效的状态\(k\)

更新过程保证头部\(val\)最优,\(k\)单调递增(因为后者的更新顺序是从左往右)

注意单调更新时只对头部更新,因为单调范围右边界总是\(S_i-1\)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define iter(i,j) for(int i=0;i<(j).size();i++)
#define print(a) printf("%lld",(ll)a)
#define println(a) printf("%lld\n",(ll)a)
#define printbk(a) printf("%lld ",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int MAXN = 2e4+11;
const int oo = 0x3f3f3f3f;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct XJB{
int l,p,s;
bool operator < (const XJB &r) const{
return s<r.s;
}
}a[MAXN];
int n,m;
int f[233][MAXN];
inline int cal(int i,int k){
return f[i-1][k]-a[i].p*k;
}
int main(){
while(cin>>n>>m){
rep(i,1,m){
a[i].l=read();
a[i].p=read();
a[i].s=read();
}
sort(a+1,a+1+m);
memset(f,0,sizeof f);
deque<int> que;
rep(i,1,m){
while(!que.empty()) que.pop_back();
rep(k,max(0,a[i].s-a[i].l),a[i].s-1){ //j-Li<=k<=Si-1,j>=Si
while(!que.empty()&&cal(i,k)>=cal(i,que.back())) que.pop_back();
que.push_back(k);
}
rep(j,1,n){
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(j>=a[i].s){
while(!que.empty()&&que.front()<j-a[i].l) que.pop_front();
if(!que.empty()) f[i][j]=max(f[i][j],cal(i,que.front())+a[i].p*j);
}
}
}
println(f[m][n]);
}
return 0;
}

POJ - 1821 单调队列优化DP + 部分笔记的更多相关文章

  1. 【笔记篇】单调队列优化dp学习笔记&&luogu2569_bzoj1855股票交♂易

    DP颂 DP之神 圣洁美丽 算法光芒照大地 我们怀着 崇高敬意 跪倒在DP神殿里 你的复杂 能让蒟蒻 试图入门却放弃 在你光辉 照耀下面 AC真心不容易 dp大概是最经久不衰 亘古不化的算法了吧. 而 ...

  2. POJ 2373 单调队列优化DP

    题意: 思路: f[i] = min(f[j]) + 1; 2 * a <= i - j <= 2 *b: i表示当前在第i个点.f[i]表示当前最少的线段个数 先是N^2的朴素DP(果断 ...

  3. poj 1821 Fence 单调队列优化dp

    /* poj 1821 n*n*m 暴力*/ #include<iostream> #include<cstdio> #include<cstring> #incl ...

  4. POJ 1821 Fence(单调队列优化DP)

    题解 以前做过很多单调队列优化DP的题. 这个题有一点不同是对于有的状态可以转移,有的状态不能转移. 然后一堆边界和注意点.导致写起来就很难受. 然后状态也比较难定义. dp[i][j]代表前i个人涂 ...

  5. 算法笔记--单调队列优化dp

    单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...

  6. 「学习笔记」单调队列优化dp

    目录 算法 例题 最大子段和 题意 思路 代码 修剪草坪 题意 思路 代码 瑰丽华尔兹 题意 思路 代码 股票交易 题意 思路 代码 算法 使用单调队列优化dp 废话 对与一些dp的转移方程,我们可以 ...

  7. 单调队列优化DP——习题收集

    前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...

  8. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  9. bzoj1855: [Scoi2010]股票交易--单调队列优化DP

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

随机推荐

  1. mosquitto ---配置SSL/TLS linux

    mosquitto ---配置SSL/TLS 摘自: https://www.cnblogs.com/saryli/p/9821343.html 在服务器电脑上面创建myCA文件夹, 如在/home/ ...

  2. AID-应用标识符的组成规则

    AID:即唯一标识一个应用,分为两部分,RID(5字节)+PIX(最多11字节) RID:注册标识符,由ISO组织来分配,标识一个全球唯一的应用提供商,一般是分配给卡组织,比如分配给Master,比如 ...

  3. myeclipse如何将项目打包成war包

    打包步骤如下: 详细介绍请查看全文:https://cnblogs.com/qianzf/ 原文博客的链接地址:https://cnblogs.com/qzf/

  4. C++11学习笔记之三lamda表达式,std::function, std::bind

    //lamda //first lamda [] {}; // second lamda []() //or no need () when paramater is null { std::cout ...

  5. java 基础语言: 方法

    方法 格式: 修饰符 返回值类型 方法名(参数类型 参数名1, 参数类型 参数名2, ...) { 方法体; return 返回值; } 方法使用的注意事项: 1,方法不调用,自己不执行 2,方法中不 ...

  6. poj2480——Longge's problem(欧拉函数)

    Longge's problem Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9190   Accepted: 3073 ...

  7. 网络安全之iptables防火墙

    1>各种传输方式到最后都会转化为能够通过网络发送的数据格式: 1>文本格式: 2>二进制格式:2>TCP三次握手连接,四次断开,连接时客户端是主动打开,服务器是被动 打开,处于 ...

  8. SQL SERVER先判断视图是否存在然后再创建视图的语句

    如果我们的语句为: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 IF NOT EXISTS(SELECT 1 FROM sys.views WHERE name='Report_I ...

  9. Android 虚拟机访问本地服务器的地址

    http://10.0.2.2:8080/test/ 比如 localhost:8080 为 tomcat 地址,然后 test 是 tomcat 目录下 webapps 的子目录. 10.0.2.2 ...

  10. 201621123012 《Java程序设计》第14次学习总结

    作业14-数据库 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 2. 使用数据库技术改造你的系统 2.1 简述如何使用数据库技术改造你的系统.要建立什么表?截 ...