【Luogu】P2254瑰丽华尔兹(堆优化DP)
我也不知道为什么脑子一抽就想了个堆优化……然后贼慢……
因为上午听不懂wys的电音专场(快速傅立叶变换),然后就做了这么一道题。
首先朴素DP很sb都能秒出。就是枚举时刻、位置(两维)然后转移。
观察发现这是O(TNM)的,可以通过50%的数据。
然后……(喂题目提示得太明显了吧)发现时间段只有200个,跟50%的T是一样的
这简直就是明说:“快往O(KNM)上想!”
然后我就不知道为啥想了个O(KNMlogn),qwq。
枚举时刻改为枚举时间段,每个时间段枚举位置用堆优化(其实应该用单调队列)转移得出答案。
虽然题目水+我的方法慢+我是sb+实现方法诡异+调了很久,1A还是很高兴的。
(实现方法智障……可以当成锻炼代码能力嘛qwq)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cctype>
#define maxn 205
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} struct Node{
int dat,pos;
bool operator <(const Node a)const{
return dat>a.dat;
}
bool operator <=(const Node a)const{
return dat>=a.dat;
}
}; struct Heap{
Node heap[];int size;
Heap(){ size=;}
inline void push(Node x){
heap[++size]=x;
register int i=size,k;
while(i>){
k=i>>;
if(heap[k]<=heap[i]) return;
swap(heap[i],heap[k]);
i=k;
}
return;
}
inline bool empty(){ return !size; }
inline Node top(){ return heap[]; }
inline void clear(){size=;}
inline void pop(){
heap[]=heap[size--];
register int i=,k;
while((i<<)<=size){
k=i<<;
if(k<size&&heap[k|]<heap[k]) k|=;
if(heap[i]<=heap[k]) return;
swap(heap[i],heap[k]);
i=k;
}
}
}; Heap s[maxn]; int last,now=;
int f[maxn][maxn][];
char mp[maxn][maxn]; struct Line{
int from,to,dir;
bool operator <(const Line a)const{ return from<a.from; }
}q[maxn]; int main(){
int n=read(),m=read(),sx=read(),sy=read(),e=read();
for(int i=;i<=n;++i) scanf("%s",mp[i]+);
for(int i=;i<=e;++i) q[i]=(Line){read(),read(),read()};
sort(q+,q+e+);
memset(f,-/,sizeof(f));
f[sx][sy][last]=;
for(int i=;i<=e;++i){
int from=q[i].from,to=q[i].to,dir=q[i].dir;
if(dir<)
for(int j=;j<=m;++j){
s[j].clear();
if(dir==){
int cnt=;
for(int k=n;k;--k){
f[k][j][now]=-;
cnt++;
if(mp[k][j]=='x'){
s[j].clear();
continue;
}
if(s[j].empty()){
f[k][j][now]=f[k][j][last];
s[j].push((Node){f[k][j][last]-cnt,k});
continue;
}
Node ret=s[j].top();
while((!s[j].empty())&&ret.pos-k>to-from+){
s[j].pop();
ret=s[j].top();
}
if(s[j].empty()){
f[k][j][now]=f[k][j][last];
s[j].push((Node){f[k][j][last]-cnt,k});
continue;
}
//printf("%d %d %d %d\n",k,j,ret.pos,f[ret.pos][j][last]+ret.pos-k);
f[k][j][now]=max(f[k][j][last],f[ret.pos][j][last]+ret.pos-k);
s[j].push((Node){f[k][j][last]-cnt,k});
}
}
else{
int cnt=;
for(int k=;k<=n;++k){
f[k][j][now]=-;
cnt++;
if(mp[k][j]=='x'){
s[j].clear();
continue;
}
if(s[j].empty()){
f[k][j][now]=f[k][j][last];
s[j].push((Node){f[k][j][last]-cnt,k});
continue;
}
Node ret=s[j].top();
while((!s[j].empty())&&k-ret.pos>to-from+){
s[j].pop();
ret=s[j].top();
}
if(s[j].empty()){
f[k][j][now]=f[k][j][last];
s[j].push((Node){f[k][j][last]-cnt,k});
continue;
}
f[k][j][now]=max(f[k][j][last],f[ret.pos][j][last]+k-ret.pos);
s[j].push((Node){f[k][j][last]-cnt,k});
}
}
}
else
for(int j=;j<=n;++j){
s[j].clear();
if(dir==){
int cnt=;
for(int k=;k<=m;++k){
f[j][k][now]=-;
cnt++;
if(mp[j][k]=='x'){
s[j].clear();
continue;
}
if(s[j].empty()){
f[j][k][now]=f[j][k][last];
s[j].push((Node){f[j][k][last]-cnt,k});
continue;
}
Node ret=s[j].top();
while((!s[j].empty())&&k-ret.pos>to-from+){
s[j].pop();
ret=s[j].top();
}
if(s[j].empty()){
f[j][k][now]=f[j][k][last];
s[j].push((Node){f[j][k][last]-cnt,k});
continue;
}
//printf("%d %d %d\n",j,k,f[j][ret.pos][last]+k-ret.pos);
f[j][k][now]=max(f[j][k][last],f[j][ret.pos][last]+k-ret.pos);
s[j].push((Node){f[j][k][last]-cnt,k});
}
}
else{
int cnt=;
for(int k=m;k;--k){
f[j][k][now]=-;
cnt++;
if(mp[j][k]=='x'){
s[j].clear();
continue;
}
if(s[j].empty()){
f[j][k][now]=f[j][k][last];
s[j].push((Node){f[j][k][last]-cnt,k});
continue;
}
Node ret=s[j].top();
while((!s[j].empty())&&ret.pos-k>to-from+){
s[j].pop();
ret=s[j].top();
}
if(s[j].empty()){
f[j][k][now]=f[j][k][last];
s[j].push((Node){f[j][k][last]-cnt,k});
continue;
}
//printf("%d %d %d\n",j,k,f[j][ret.pos][last]+ret.pos-k);
f[j][k][now]=max(f[j][k][last],f[j][ret.pos][last]+ret.pos-k);
s[j].push((Node){f[j][k][last]-cnt,k});
}
}
}
swap(now,last);
}
int ans=;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j) ans=max(ans,f[i][j][last]);
printf("%d\n",ans);
return ;
}
【Luogu】P2254瑰丽华尔兹(堆优化DP)的更多相关文章
- 【BZOJ1499】[NOI2005]瑰丽华尔兹 单调队列+DP
[BZOJ1499][NOI2005]瑰丽华尔兹 Description 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是 ...
- 洛谷P1725 琪露诺 (单调队列/堆优化DP)
显然的DP题..... 对于位置i,它由i-r~i-l的位置转移过来,容易得到方程 dp[i]=dp[i]+max(dp[i−r],...,dp[i−l]). 第一种:n2的暴力,只能拿部分分. 1 ...
- 征途堆积出友情的永恒「堆优化dp」
直接写题解: 很简单的dp暴力转移式子:f[i]=MAX{f[j]+max(tax[j],sum[i]-sum[j])} 观察式子,只有一个变量sum[i]; 而其他都为定量; 则考虑维护 两个定量: ...
- 单调队列优化DP || [NOI2005]瑰丽华尔兹 || BZOJ 1499 || Luogu P2254
题外话:题目极好,做题体验极差 题面:[NOI2005]瑰丽华尔兹 题解: F[t][i][j]表示第t时刻钢琴位于(i,j)时的最大路程F[t][i][j]=max(F[t-1][i][j],F[t ...
- luogu P2254 [NOI2005]瑰丽华尔兹
题目链接 luogu P2254 [NOI2005]瑰丽华尔兹 题解 为什么我我我不放放放bzoj的链接呢? 因为打的暴力啊,然后bzojT了呀QAQQQQQ(逃 然后luogu竟然过了呀呀呀 dp[ ...
- BZOJ 1499 [NOI2005] 瑰丽华尔兹 | 单调队列优化DP
BZOJ 1499 瑰丽华尔兹 | 单调队列优化DP 题意 有一块\(n \times m\)的矩形地面,上面有一些障碍(用'#'表示),其余的是空地(用'.'表示).每时每刻,地面都会向某个方向倾斜 ...
- bzoj1499[NOI2005]瑰丽华尔兹 单调队列优化dp
1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 1802 Solved: 1097[Submit][Status ...
- 2018.09.10 bzoj1499: [NOI2005]瑰丽华尔兹(单调队列优化dp)
传送门 单调队列优化dp好题. 这题其实很简单. 我们很容易想到一个O(T∗n∗m)" role="presentation" style="position: ...
- bzoj 1499 [NOI2005]瑰丽华尔兹——单调队列优化dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1499 简单的单调队列优化dp.(然而当时却WA得不行.今天总算填了坑) 注意滚动数组赋初值应 ...
随机推荐
- 发现知乎的一个Bug,并且我绕过了此Bug,沾沾自喜中...
发现问题 在知乎点击修改头像,上传图片时发现一片空白.凭着程序员的直觉,第一反应时看下控制台是否有报错.果然发现如下: Refused to load the image 'data:image/jp ...
- MovieReview—Transformers.The.Last.Knight.(变形金刚5:最后的骑士.)
Gorgeous Effect & Bad Plot I can only say that the movie's effects are shocking. However, the ...
- python_81_标准库_时间模块
''' 标准库: 1.time 时间的三种表示方法:a:时间戳(timestamp) b:格式化的时间字符串 c:元组(struct_time)共九个元素 time.struct_time(tm_ye ...
- 如何通过修改文件添加用户到sudoers上
su - root chmod u+w /etc/sudoers (该文件没有写权限, 修改)vim /etc/sudoers 按下 I 键进行编写 # User privilege speci ...
- Java基础面试操作题:线程同步代码块 两个客户往一个银行存钱,每人存三十次一次存一百。 模拟银行存钱功能,时时银行现金数。
package com.swift; public class Bank_Customer_Test { public static void main(String[] args) { /* * 两 ...
- TreeMap 底层是红黑树 排序是根据key值进行的 添加元素时异常 Comparable异常 Comparator比较自定义对象放在键的位置
package com.swift; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; ...
- iOS9适配总结
每年iOS升级,都会带来一些坑,这次iOS9也不例外.本文总结了微信在适配iOS9上遇到的问题和解决方案. 一.iOS9问题汇总 1. 编译问题(Bitcode) 大部分人升级到Xcode7后,首 ...
- MFC 菜单编程 -- 总结
菜单结构 一个菜单栏可以有若干个子菜单,而一个子菜单又可有若干个菜单项.对于菜单栏的子菜单,由左至右从0开始索引.对于特定的子菜单的菜单项,由上至下建立从0开始的索引.访问子菜单和菜单项,均可通过其索 ...
- salt常用模块
salt 常用命令整理 转载:https://www.cnblogs.com/aslongas/p/6964890.html salt 常用命令整理 ***********模块******** ...
- 面向对象之元类(metaclass)
一.前言: 要搞懂元类必须要搞清楚下面几件事: 类创建的时候,内部过程是什么样的,也就是我们定义类class 类名()的过程底层都干了些啥 类的调用即类的实例化过程的了解与分析 我们已经知道元类存在的 ...