POJ1821 单调队列//ST表 优化dp
http://poj.org/problem?id=1821
当我们在考虑内层循环j以及决策k的时候,我们可以把外层变量i看作定值,以此来优化dp状态转移方程。
题意 有n个工人准备铺m个连续的墙,每个工人有他必须图的一面墙壁Si,最多连续铺Li,每铺一个就花费Ci的钱,问最多要多少钱;
朴素算法很好想,就dp[i][j]维护i工人到这j层墙壁的最大值,对于每个工人去枚举他涂墙壁的开头和结尾然后更新即可。
时间复杂度O(NMM) M的范围是16000,很显然会T,我们考虑状态转移方程。
对于每个工人,dp[i][j]的更新是寻找一个k使得dp[i - 1][k - 1] + (j - k + 1 ) * P 最大;
在这个转移方程里,我们将i看作定值,除了状态变量j之外还有一个决策j,看似很难处理,我们将方程变形.
dp[i][j]的更新变为 max(dp[i - 1][k - 1] - (k - 1) * P) + j * P;
在这一层中,最大值的寻找仅和k有关,而k事实上对每一个i都是可以预处理出来的,在j查询的时候只有范围变动,问题就变成了常规的优化区间最大值的问题。
这里附上用ST表优化和单调队列优化的两种方法。
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = ;
const int maxm = ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K;
inline int read()
{
int now=;register char c=getchar();
for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());
return now;
}
struct Node{
int L,P,S;
}node[maxn];
int dp[][maxm];
bool cmp(Node a,Node b){
return a.S < b.S;
}
int DP[maxm][];
int mm[maxm];
int num[maxm];
void initRMQ(int n,int b[]){
mm[] = -;
for(int i = ; i <= n ; i ++){
mm[i] = ((i & (i - )) == ) ? mm[i - ] + :mm[i - ];
DP[i][] = b[i];
}
for(int j = ; j <= mm[n]; j ++){
for(int i = ; i + ( << j) - <= n ; i++){
DP[i][j] = max(DP[i][j - ],DP[i + ( << (j - ))][j - ]);
}
}
}
int rmq(int x,int y){
int k = mm[y - x + ];
return max(DP[x][k],DP[y - ( << k) + ][k]);
}
int main()
{
while(~Sca2(N,K)){
For(i,,K){
scanf("%d%d%d",&node[i].L,&node[i].P,&node[i].S);
}
sort(node + ,node + + K,cmp);
Mem(dp,);
For(i,,K){
Mem(num,);
Mem(dp[i & ],);
for(int k = max(node[i].S - node[i].L + ,); k <= node[i].S; k ++){
num[k] = dp[i - & ][k - ] - node[i].P * (k - );
}
initRMQ(node[i].S,num);
For(j,,N){
dp[i & ][j] = max(dp[i - & ][j],dp[i & ][j - ]);
if(j >= node[i].S && j <= node[i].S + node[i].L - ){
dp[i & ][j] = max(dp[i & ][j],rmq(max(j - node[i].L + ,),node[i].S) + node[i].P * j);
}
}
}
Pri(dp[K & ][N]);
}
#ifdef VSCode
system("pause");
#endif
return ;
}
ST表优化
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = ;
const int maxm = ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K;
inline int read()
{
int now=;register char c=getchar();
for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());
return now;
}
struct Node{
int L,P,S;
}node[maxn];
int dp[][maxm];
bool cmp(Node a,Node b){
return a.S < b.S;
}
int Queue[maxm];
int head,tail;
int main()
{
while(~Sca2(N,K)){
For(i,,K){
scanf("%d%d%d",&node[i].L,&node[i].P,&node[i].S);
}
sort(node + ,node + + K,cmp);
Mem(dp,);
For(i,,K){
head = ; tail = ;
Mem(dp[i & ],);
for(int k = max(node[i].S - node[i].L + ,); k <= node[i].S; k ++){
int ans = dp[i - & ][k - ] - node[i].P * (k - );
while(head <= tail && dp[i - & ][Queue[tail] - ] - node[i].P * (Queue[tail] - )<= ans) tail--;
Queue[++tail] = k;
}
For(j,,N){
dp[i & ][j] = max(dp[i - & ][j],dp[i & ][j - ]);
if(j >= node[i].S){
while(head <= tail && Queue[head] < j - node[i].L + ) head++;
if(head <= tail) dp[i & ][j] = max(dp[i & ][j],dp[i - & ][Queue[head] - ] + (j - Queue[head] + ) * node[i].P);
}
}
}
Pri(dp[K & ][N]);
}
#ifdef VSCode
system("pause");
#endif
return ;
}
单调队列优化
值得一提的是单调队列的查询和处理的时间都是线性的,总时间复杂度为O(NM),而ST表的预处理要用到nlnn,所以用时会比ST表快一些
POJ1821 单调队列//ST表 优化dp的更多相关文章
- P6087 [JSOI2015]送礼物 01分数规划+单调队列+ST表
P6087 [JSOI2015]送礼物 01分数规划+单调队列+ST表 题目背景 \(JYY\) 和 \(CX\) 的结婚纪念日即将到来,\(JYY\) 来到萌萌开的礼品店选购纪念礼物. 萌萌的礼品店 ...
- HDU 4123 Bob's Race:树的直径 + 单调队列 + st表
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123 题意: 给你一棵树,n个节点,每条边有长度. 然后有m个询问,每个询问给定一个q值. 设dis[ ...
- Luogu P1198 [JSOI2008]最大数 单调队列/ST表
开一个单调队列,下标递增,值递减. 然后在上面二分最大数. 如果加上并查集可以做到接近线性. 还有一种是插入一个数然后,从后向前更新ST表. #include<cstdio> #inclu ...
- Codevs 4373 窗口(线段树 单调队列 st表)
4373 窗口 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题目描述 Description 给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只 ...
- APIO2010特别行动队(单调队列、斜率优化)
其实这题一看知道应该是DP,再一看数据范围肯定就是单调队列了. 不过我还不太懂神马单调队列.斜率优化…… 附上天牛的题解:http://www.cnblogs.com/neverforget/arch ...
- [bzoj4540][Hnoi2016][序列] (莫队算法+单调栈+st表)
Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar.若1≤l≤s≤t≤r≤n,则称a ...
- Max answer(单调栈+ST表)
Max answer https://nanti.jisuanke.com/t/38228 Alice has a magic array. She suggests that the value o ...
- BZOJ3879:SvT(后缀数组,单调栈,ST表)
Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...
- BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】
题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...
随机推荐
- Xamarin + MvvmCross 安装 Part 1
前言 最近,由于工作需要,公司准备开发移动端APP.临近年底,公司不准备大面招人,由于公司一直基于.net平台进行开发,本人自告奋勇,准备先用xamarin做下移动开发.开始了在网上不停的google ...
- hibernate主配置文件中指定session与当前线程绑定
配置一条属性 <property name="hibernate.current_session_context_class">thread</property& ...
- codeforces158C
Cd and pwd commands CodeForces - 158C Vasya is writing an operating system shell, and it should have ...
- Nginx 缓存深入理解
100课陶辉 proxy_cache_methods 指令主要是根据请求方法指定是否使用缓存 Syntax: proxy_cache_methods GET | HEAD | POST ...; De ...
- Centos 7安装和配置 ElasticSearch入门小白
实验环境: 操作系统:Centos 7.5 服务器ip:192.168.1.198 运行用户:root 网络环境:Internet 在企业生产环境有很多服务器的时候.很多业务模块的日志的时候运维人员需 ...
- Android与H5交互 原理与对比
原文: https://www.jianshu.com/p/345f4d8a5cfa 1.Android调用JS的方法有2种: (1)通过WebView的loadUrl() // 调用js中的函数: ...
- ie11的版本判断
我的电脑昨天更新的时候把ie11给更新出来了,然后发现我的skylineweb项目提示我的浏览器不是ie,这样显然是浏览器检测出现了问题.查找后找到了下面的解决方法.大家的电脑如果也更新成了ie11的 ...
- Zookeeper注册中心底层实现小记
内容摘自微信公众号,程序员小灰.推荐-ing Zookeeper的数据模型 Zookeeper的数据模型是什么样子呢?它很像数据结构当中的树,也很像文件系统的目录. 树是由节点所组成,Zookeepe ...
- P1427 小鱼念数字
P1427 题目描述 小鱼最近被要求参加一个数字游戏,要求它把看到的一串数字(长度不一定,以0结束,最多不超过100个,数字不超过2^32-1),记住了然后反着念出来(表示结束的数字0就不要念出来了) ...
- Cetos 中添加bbr服务
说明:此方法只适用于KVM架构的,OpenVZ平台无法使用: 一:安装bbr服务: # wget --no-check-certificate https://github.com/teddysun/ ...