[luoguP1970] 花匠(DP)
n2 过不了惨啊
70分做法
f[i][0] 表示第 i 个作为高的,的最优解
f[i][0] 表示第 i 个作为低的,的最优解
(且第 i 个一定选)
那么
f[i+1][1]=max(f[j][0])+1,i>=j>=1,h[j]>h[i+1],
f[i+1][0]=max(f[j][1])+1,i>=j>=1,h[j]<h[i+1],
——代码
#include <cstdio>
#include <algorithm> const int MAXN = , INF = ~( << );
int n, ans, max;
int a[MAXN], f[MAXN][]; inline int Max(int x, int y)
{
return x > y ? x : y;
} int main()
{
//freopen("flower.in", "r", stdin);
//freopen("flower.out", "w", stdout);
int i, j;
scanf("%d", &n);
for(i = ; i <= n; i++) scanf("%d", &a[i]);
for(i = ; i <= n; i++)
{
max = ;
for(j = ; j < i; j++)
if(a[j] < a[i] && f[j][] > max)
max = f[j][];
f[i][] = max + ;
ans = Max(ans, f[i][]);
max = ;
for(j = ; j < i; j++)
if(a[j] > a[i] && f[j][] > max)
max = f[j][];
f[i][] = max + ;
ans = Max(ans, f[i][]);
}
printf("%d\n", ans);
return ;
}
100分
我们发现上面的方程可以用线段树优化,可以建一颗权值线段树
#include <cstdio>
#include <iostream>
#include <algorithm>
#define root 1, 1, size
#define ls now << 1, l, mid
#define rs now << 1 | 1, mid + 1, r const int MAXN = ;
int n, size;
int a[MAXN], b[MAXN], f[MAXN][], max[MAXN << ][]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline int Max(int x, int y)
{
return x > y ? x : y;
} inline void pushup(int now)
{
max[now][] = Max(max[now][], max[now << ][]);
max[now][] = Max(max[now][], max[now << | ][]);
max[now][] = Max(max[now][], max[now << ][]);
max[now][] = Max(max[now][], max[now << | ][]);
} inline int query(int x, int y, int k, int now, int l, int r)
{
if(x <= l && r <= y) return max[now][k];
int mid = (l + r) >> ;
if(l > y || r < x) return ;
return Max(query(x, y, k, ls), query(x, y, k, rs));
} inline void update(int x, int a, int b, int now, int l, int r)
{
if(l == r)
{
max[now][] = Max(max[now][], a);
max[now][] = Max(max[now][], b);
return;
}
int mid = (l + r) >> ;
if(x <= mid) update(x, a, b, ls);
else update(x, a, b, rs);
pushup(now);
} int main()
{
int i;
n = read();
for(i = ; i <= n; i++) a[i] = b[i] = read();
std::sort(b + , b + n + );
size = std::unique(b + , b + n + ) - (b + );
for(i = ; i <= n; i++) a[i] = std::lower_bound(b + , b + size + , a[i]) - b;
for(i = ; i <= n; i++)
{
f[i][] = query(, a[i] - , , root) + ;
f[i][] = query(a[i] + , size, , root) + ;
update(a[i], f[i][], f[i][], root);
}
printf("%d\n", Max(f[n][], f[n][]));
return ;
}
100分
用个p线段树,树状数组维护前后缀就好。
#include <cstdio>
#include <iostream>
#include <algorithm>
#define root 1, 1, size
#define ls now << 1, l, mid
#define rs now << 1 | 1, mid + 1, r const int MAXN = ;
int n, ans;
int c0[MAXN], c1[MAXN]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline int max(int x, int y)
{
return x > y ? x : y;
} inline int query1(int x)
{
int ret = ;
for(; x <= MAXN; x += x & -x) ret = max(ret, c1[x]);
return ret;
} inline int query0(int x)
{
int ret = ;
for(; x; x -= x & -x) ret = max(ret, c0[x]);
return ret;
} inline void update0(int x, int d)
{
for(; x <= MAXN; x += x & -x) c0[x] = max(c0[x], d);
} inline void update1(int x, int d)
{
for(; x; x -= x & -x) c1[x] = max(c1[x], d);
} int main()
{
int i, x, y, z;
n = read();
for(i = ; i <= n; i++)
{
z = read() + ;
x = query1(z + ) + ;
y = query0(z - ) + ;
update0(z, x);
update1(z, y);
ans = max(ans, max(x, y));
}
printf("%d\n", ans);
return ;
}
100分
f[i][0] 表示第 i 个作为高的,的最优解
f[i][0] 表示第 i 个作为低的,的最优解
(然而第 i 个不一定选)
那么
h[i]>h[i−1]时,
f[i][0]=max{f[i−1][0],f[i−1][1]+1},f[i][1]=f[i−1][1];
h[i]==h[i−1]时,
f[i][0]=f[i−1][0],f[i][1]=f[i−1][1];
h[i]<h[i−1]时,
f[i][0]=f[i−1][0],f[i][1]=max{f[i−1][1],f[i−1][0]+1}.
答案ans=max{f[n][0],f[n][1]};
边界为f[1][0]=f[1][1]=1
——代码
#include <cstdio>
#include <algorithm> const int MAXN = , INF = ~( << );
int n, ans;
int a[MAXN], f[MAXN][]; inline int max(int x, int y)
{
return x > y ? x : y;
} int main()
{
//freopen("flower.in", "r", stdin);
//freopen("flower.out", "w", stdout);
int i, j;
scanf("%d", &n);
for(i = ; i <= n; i++) scanf("%d", &a[i]);
f[][] = f[][] = ;
for(i = ; i <= n; i++)
{
if(a[i] > a[i - ])
{
f[i][] = max(f[i - ][], f[i - ][] + );
f[i][] = f[i - ][];
}
else if(a[i] == a[i - ])
{
f[i][] = f[i - ][];
f[i][] = f[i - ][];
}
else
{
f[i][] = f[i - ][];
f[i][] = max(f[i - ][], f[i - ][] + );
}
}
printf("%d\n", max(f[n][], f[n][]));
return ;
}
[luoguP1970] 花匠(DP)的更多相关文章
- 洛谷 P1970 花匠 —— DP
题目:https://www.luogu.org/problemnew/show/P1970 普通的DP,f[i][0/1] 表示 i 处处于较小或较大的长度: 注意:1.树状数组向后 query 时 ...
- $Noip2013/Luogu1970$ 花匠 $dp$+思维
$Luogu$ $Sol$ 和$Poj1037\ A\ Decorative\ Fence$好像吖. $f[i][0/1]$表示前$i$个数,且选了第$i$个数,这个数相对于上一个数是下降(上升)的, ...
- NOIP2013 花匠 DP 线段树优化
网上一堆题解,我写的是N^2优化的那种,nlogn,O(n)的那种能看懂,但是让我自己在赛场写,肯定没戏了 #include <cstdio> #include <iostream& ...
- luogu1970 花匠(dp)
设f1[i]表示以1..i中某个合法序列的长度,而且最后一位是较大的 f2[i]表示以1..i中某个合法序列的长度,而且最后一位是较小的 那么就有$f1[i]=max\{f2[j]+1\},(j< ...
- 洛谷P1970 花匠(dp)
题意 题目链接 Sol 直接用\(f[i][0/1]\)表示到第\(i\)个位置,该位置是以上升结尾还是以下降结尾 转移的时候只需枚举前一个即可 #include<cstdio> #inc ...
- NOIP2013 提高组合集
NOIP 2013 提高组 合集 D1 T1 转圈游戏 快速幂裸题 #include <iostream> #include <cstdio> #include <cst ...
- $NOIp$提高组历年题目复习
写在前面 一个简略的\(NOIp\)题高组历年题目复习记录.大部分都有单独写题解,但懒得放\(link\)了\(QwQ\).对于想的时候兜了圈子的题打上\(*\). \(NOIp2018\ [4/6] ...
- DP练习题——洛谷P1970花匠
目录 题目描述: 输入输出格式: 输入格式: 输出格式: 输入输出样例: 输入样例: 输出样例: 题目分析: 解法一: 解法二: 结语: 题目描述: 洛谷\(P1970\) 花匠栋栋种了一排花,每株花 ...
- [DP][NOIP2013]花匠
花匠 问题描述: 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. ...
随机推荐
- JEECMS9.3集成dubbo操作记录
需求描述: 门户及其他应用系统需要查询JEECMS9.3中发布的栏目及数据,而其他系统都是基于dubbo开发的,因此想要将JEECMS9.3中集成dubbo并对外提供内容管理服务. 需求实现: 1.添 ...
- vue项目导出电子表格
方法一: 一.安装依赖(前面基本一样) npm install file-saver --save npm install xlsx --save npm install script-loader ...
- 白话容器namespace
进入正题之前是例行装X环节: 过年7天吃的,花了45天又回来了. 近年来容器大火,也正是因为容器,生生灭掉了一个IT岗位!哥也是被生生的逼上了邪路. 那究竟什么是容器呢? 就三个字:它就是个进程!(多 ...
- SOA测试之浏览器插件
1. Chrome HTTP Rest Client 插件: 1.1 Postman: https://chrome.google.com/webstore/detail/postman-rest-c ...
- 【C++】模板简述(三):类模板
上文简述了C++模板中的函数模板的格式.实例.形参.重载.特化及参数推演,本文主要介绍类模板. 一.类模板格式 类模板也是C++中模板的一种,其格式如下: template<class 形参名1 ...
- 什么是LambdaExpression,如何转换成Func或Action(2)
序言 在上一篇中,我们认识了什么是表达式树.什么是委托,以及它们的关系.可能是我功力不好,貌似大家都不怎么关注,没有讲解出不同角度的问题. 学习一种新技术,是枯燥的过程,只有在你掌握后并能运用时才能从 ...
- C#枚举中的位运算权限分配
什么是位运算 常用的位运算主要有与(&), 或(|)和非(~), 比如: & = ; | = ; ~ = ; 运用在权限设计中 先建立一个枚举表示所有的权限管理操作: [Flags] ...
- swift不同地方 命名空间module iOS
Objective-C没有命名空间,为了避免冲突,Objective-C的类型一般都会加上两到三个字母的前缀,比如Apple保留的NS和UI前缀,各个系统框架的前缀,各个系统框架的前缀SK(Store ...
- 用数据集跑一个模型遇到bug如何解决
自己在用fast rcnn和ssd跑自己数据集过程中都遇到了bug,fast rcnn中是loss下降但值较高,并且测试出来结果一直不对,ssd是loss从一开始到后面loss都一直为0. 遇到这种情 ...
- ssd训练自己的数据集
1.在ssd/caffe/data下创建VOC2007的目录,将ssd/caffe/data/VOC0712里的create_data.sh.create_list.sh和labelmap_voc.p ...