传送门

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)的更多相关文章

  1. 洛谷 P1970 花匠 —— DP

    题目:https://www.luogu.org/problemnew/show/P1970 普通的DP,f[i][0/1] 表示 i 处处于较小或较大的长度: 注意:1.树状数组向后 query 时 ...

  2. $Noip2013/Luogu1970$ 花匠 $dp$+思维

    $Luogu$ $Sol$ 和$Poj1037\ A\ Decorative\ Fence$好像吖. $f[i][0/1]$表示前$i$个数,且选了第$i$个数,这个数相对于上一个数是下降(上升)的, ...

  3. NOIP2013 花匠 DP 线段树优化

    网上一堆题解,我写的是N^2优化的那种,nlogn,O(n)的那种能看懂,但是让我自己在赛场写,肯定没戏了 #include <cstdio> #include <iostream& ...

  4. luogu1970 花匠(dp)

    设f1[i]表示以1..i中某个合法序列的长度,而且最后一位是较大的 f2[i]表示以1..i中某个合法序列的长度,而且最后一位是较小的 那么就有$f1[i]=max\{f2[j]+1\},(j< ...

  5. 洛谷P1970 花匠(dp)

    题意 题目链接 Sol 直接用\(f[i][0/1]\)表示到第\(i\)个位置,该位置是以上升结尾还是以下降结尾 转移的时候只需枚举前一个即可 #include<cstdio> #inc ...

  6. NOIP2013 提高组合集

    NOIP 2013 提高组 合集 D1 T1 转圈游戏 快速幂裸题 #include <iostream> #include <cstdio> #include <cst ...

  7. $NOIp$提高组历年题目复习

    写在前面 一个简略的\(NOIp\)题高组历年题目复习记录.大部分都有单独写题解,但懒得放\(link\)了\(QwQ\).对于想的时候兜了圈子的题打上\(*\). \(NOIp2018\ [4/6] ...

  8. DP练习题——洛谷P1970花匠

    目录 题目描述: 输入输出格式: 输入格式: 输出格式: 输入输出样例: 输入样例: 输出样例: 题目分析: 解法一: 解法二: 结语: 题目描述: 洛谷\(P1970\) 花匠栋栋种了一排花,每株花 ...

  9. [DP][NOIP2013]花匠

    花匠 问题描述: 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. ...

随机推荐

  1. 专 linux命令之set x详解

    set -x与set +x指令   用于脚本调试.set是把它下面的命令打印到屏幕 set -x 是开启 set +x是关闭 set -o是查看 (xtrace),set去追中一段代码的显示情况. 执 ...

  2. [书目20141009]《ReWork》

    ReWork1: ============= 引言篇INTRODUCTION开局篇FIRST 新的现实缷负篇TAKEDOWNS 忘了“现实世界” 哪来的从错误中学习 计划即瞎猜 何必壮大? 工作狂 受 ...

  3. Android开发学习——高德地图的实现

    1.首先做好下边的准备: 1.1  http://lbs.amap.com/   注册账号 1.2  下载 定位sdk 和 地图sdk 下载后是这样的 1.3  对下载的进行解压 将他们加入 中,对每 ...

  4. .net 发送邮件验证码

    using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Ma ...

  5. listBox 搜索左右移动

    <td align="left" width="50%"> 查询:<asp:TextBox ID="SacffSearch" ...

  6. Caused by: javax.el.PropertyNotFoundException: Property 'product' not found on type java.lang.String

    今天在JSP利用EL表达式取值报了 "javax.el.PropertyNotFoundException”,经过debug和打印将问题定位到这段代码: HTML应该是没啥问题,看提示在ja ...

  7. mysql 修改 root 密码

    5.76中加了一些passwd的策略 MySQL's validate_password plugin is installed by default. This will require that ...

  8. java synchronized(object/this)的 区别

    1.synchronized(object) package test.thread; import java.io.IOException; import org.junit.Test; /* * ...

  9. python学习笔记-02

    四.函数 1.定义函数 (1)定义规则 介绍列表方法的时候已经大概说过函数,学过数学的人都知道函数,给一个参数返回一个值.函数也可以自己定义.用如下的格式: >>>def 函数名(参 ...

  10. Java多线程编程核心技术---Lock的基本概念和使用

    Lock接口: ReentrantLock的基本功能: ReentrantLock的lock和unlock方法进行加锁,解锁.可以起到和synchronized关键字一样的效果: 选择性通知!!!: ...