【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得不行.今天总算填了坑) 注意滚动数组赋初值应 ...
随机推荐
- CF Gym 100187B A Lot of Joy (古典概型)
题意:给两个一样的只含有26个小写字母的字符串,然后两个分别做一下排列,问如果对应位置的字母相等那么就愉悦值就加一,问愉悦值的期望是多少? 题解:只考虑两个序列相对的位置,那么就相当于固定一个位置,另 ...
- leetcode 179. Largest Number 、剑指offer33 把数组排成最小的数
这两个题几乎是一样的,只是leetcode的题是排成最大的数,剑指的题是排成最小的 179. Largest Number a.需要将数组的数转换成字符串,然后再根据大小排序,这里使用to_strin ...
- ios sinaweibo 客户端(三)
这个页面要讲述的是用户的粉丝列表,下面是效果图: 可以看到这个视图明显也是一个tableview,在每一个cell中包含的有三个部分的内容:粉丝头像image,粉丝昵称label,我和粉丝之间的相互关 ...
- Re:从零开始的Linux之路(目录配置)
基于 Red Hat Enterprise Linux 7.5 或者 CentOS 7.4 FHS协议(Filesystem Hierarchy Standard)——文件系统层次化标准 该标准定义了 ...
- init0-6(启动级别)
一. init是Linux系统操作中不可缺少的程序之一. 所谓的init进程,它是一个由内核启动的用户级进程. 内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后, ...
- LeetCode1090. 受标签影响的最大值
问题: 我们有一个项的集合,其中第 i 项的值为 values[i],标签为 labels[i]. 我们从这些项中选出一个子集 S,这样一来: |S| <= num_wanted 对于任意的标签 ...
- day3-python 登录
import datetime # 1. f = open('users') result = f.read() f.close() user_list = result.split() # user ...
- 二叉苹果树——树形Dp(由根到左右子树的转移)
题意:给出一个二叉树,每条边上有一定的边权,并且剪掉一些树枝,求留下 Q 条树枝的最大边权和. ( 节点数 n ≤100,留下的枝条树 Q ≤ n ,所有边权和 ∑w[i] ≤30000 ) 细节:对 ...
- Android的初步探索之Context类
最近一直在学安卓,但由于JAVA的能力有限,学起应用开发来很吃力,众多错综复杂的类和界面组件弄的人焦头烂额,往往不知从何下手.... 各种名字冗长的方法和常量,没有任何界面编程的经验真是蛋疼死了.总是 ...
- flask-博客文章
提交和显示博客文章 文章模型 class Post(db.Model): __tablename__ = 'posts' id = db.Column(db.Integer, primary_key= ...