传送门

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. 影响TCP连接寿命的因素

    NAT超时 大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT 表中的对应项,造成链路中断.NAT超时是影响TCP连接寿命的一个重要因素(尤其是国内),所以客户端自动测算NAT超时 ...

  2. TestNG基本注解(一)

    TestNG基本注解   注解 描述 @BeforeSuite 注解的方法将只运行一次,运行所有测试前此套件中. @AfterSuite 注解的方法将只运行一次此套件中的所有测试都运行之后. @Bef ...

  3. windowsEvents

    今天我们要实现这个关闭窗口的功能,就是点窗口的那个叉叉它会关闭. 设计窗口的事件就是WindowsEvents,而与之有关的监听器就是WindowsListener WindowsListener也是 ...

  4. 一命令安装nginx

    #!/bin/bash yum -y install wget pcre-devel openssl openssl-devel libtool gcc automake autoconf libto ...

  5. TNS-00511: 无监听程序

    这里到服务里面打开 tns 的监听服务

  6. 重构29-Remove Middle Man(去掉中间人)

    有时你的代码里可能会存在一些"Phantom"或"Ghost"类,Fowler称之为"中间人(Middle Man)".这些中间人类仅仅简单 ...

  7. 关于TREEVIEW的ONSELECTEDNODECHANGED事件

    MSDN:http://msdn.microsoft.com/zh-cn/library/system.web.ui.webcontrols.treeview.selectednodechanged( ...

  8. K近邻法(K-Nearest Neighbor,KNN)

    KNN是一种基本分类与回归方法,本篇只总结分类问题中的KNN. 输入:样本的特征向量,对应于特征空间中的点 输出:样本的类别,可取多类 算法思想:给定一个样本类别已知的训练数据集,对于新样本,根据其K ...

  9. H5 canvas-小球抛物线

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 类方法__setattr__,__delattr__,__getattr__

    __getattr__,_delattr_,_getattr_ class Foo: x = 1 def __init__(self, y): self.y = y def __getattr__(s ...