zoukankan      html  css  js  c++  java
  • [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],

    ——代码

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 const int MAXN = 100001, INF = ~(1 << 31);
     5 int n, ans, max;
     6 int a[MAXN], f[MAXN][2];
     7 
     8 inline int Max(int x, int y)
     9 {
    10     return x > y ? x : y;
    11 }
    12 
    13 int main()
    14 {
    15     //freopen("flower.in", "r", stdin);
    16     //freopen("flower.out", "w", stdout);
    17     int i, j;
    18     scanf("%d", &n);
    19     for(i = 1; i <= n; i++) scanf("%d", &a[i]);
    20     for(i = 1; i <= n; i++)
    21     {
    22         max = 0;
    23         for(j = 1; j < i; j++)
    24             if(a[j] < a[i] && f[j][1] > max)
    25                 max = f[j][1];
    26         f[i][0] = max + 1;
    27         ans = Max(ans, f[i][0]);
    28         max = 0;
    29         for(j = 1; j < i; j++)
    30             if(a[j] > a[i] && f[j][0] > max)
    31                 max = f[j][0];
    32         f[i][1] = max + 1;
    33         ans = Max(ans, f[i][1]);
    34     }
    35     printf("%d
    ", ans);
    36     return 0;
    37 }
    View Code

    100分

    我们发现上面的方程可以用线段树优化,可以建一颗权值线段树

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #define root 1, 1, size
     5 #define ls now << 1, l, mid
     6 #define rs now << 1 | 1, mid + 1, r
     7 
     8 const int MAXN = 100001;
     9 int n, size;
    10 int a[MAXN], b[MAXN], f[MAXN][2], max[MAXN << 2][2];
    11 
    12 inline int read()
    13 {
    14     int x = 0, f = 1;
    15     char ch = getchar();
    16     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    17     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    18     return x * f;
    19 }
    20 
    21 inline int Max(int x, int y)
    22 {
    23     return x > y ? x : y;
    24 }
    25 
    26 inline void pushup(int now)
    27 {
    28     max[now][0] = Max(max[now][0], max[now << 1][0]);
    29     max[now][0] = Max(max[now][0], max[now << 1 | 1][0]);
    30     max[now][1] = Max(max[now][1], max[now << 1][1]);
    31     max[now][1] = Max(max[now][1], max[now << 1 | 1][1]);
    32 }
    33 
    34 inline int query(int x, int y, int k, int now, int l, int r)
    35 {
    36     if(x <= l && r <= y) return max[now][k];
    37     int mid = (l + r) >> 1;
    38     if(l > y || r < x) return 0;
    39     return Max(query(x, y, k, ls), query(x, y, k, rs));
    40 }
    41 
    42 inline void update(int x, int a, int b, int now, int l, int r)
    43 {
    44     if(l == r)
    45     {
    46         max[now][0] = Max(max[now][0], a);
    47         max[now][1] = Max(max[now][1], b);
    48         return; 
    49     }
    50     int mid = (l + r) >> 1;
    51     if(x <= mid) update(x, a, b, ls);
    52     else update(x, a, b, rs);
    53     pushup(now);
    54 }
    55 
    56 int main()
    57 {
    58     int i;
    59     n = read();
    60     for(i = 1; i <= n; i++) a[i] = b[i] = read();
    61     std::sort(b + 1, b + n + 1);
    62     size = std::unique(b + 1, b + n + 1) - (b + 1);
    63     for(i = 1; i <= n; i++) a[i] = std::lower_bound(b + 1, b + size + 1, a[i]) - b;
    64     for(i = 1; i <= n; i++)
    65     {
    66         f[i][0] = query(1, a[i] - 1, 1, root) + 1;
    67         f[i][1] = query(a[i] + 1, size, 0, root) + 1;
    68         update(a[i], f[i][0], f[i][1], root);
    69     }
    70     printf("%d
    ", Max(f[n][0], f[n][1]));
    71     return 0;
    72 }
    View Code

    100分

    用个p线段树,树状数组维护前后缀就好。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #define root 1, 1, size
     5 #define ls now << 1, l, mid
     6 #define rs now << 1 | 1, mid + 1, r
     7 
     8 const int MAXN = 1000002;
     9 int n, ans;
    10 int c0[MAXN], c1[MAXN];
    11 
    12 inline int read()
    13 {
    14     int x = 0, f = 1;
    15     char ch = getchar();
    16     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    17     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    18     return x * f;
    19 }
    20 
    21 inline int max(int x, int y)
    22 {
    23     return x > y ? x : y;
    24 }
    25 
    26 inline int query1(int x)
    27 {
    28     int ret = 0;
    29     for(; x <= MAXN; x += x & -x) ret = max(ret, c1[x]);
    30     return ret;
    31 }
    32 
    33 inline int query0(int x)
    34 {
    35     int ret = 0;
    36     for(; x; x -= x & -x) ret = max(ret, c0[x]);
    37     return ret;
    38 }
    39 
    40 inline void update0(int x, int d)
    41 {
    42     for(; x <= MAXN; x += x & -x) c0[x] = max(c0[x], d);
    43 }
    44 
    45 inline void update1(int x, int d)
    46 {
    47     for(; x; x -= x & -x) c1[x] = max(c1[x], d);
    48 }
    49 
    50 int main()
    51 {
    52     int i, x, y, z;
    53     n = read();
    54     for(i = 1; i <= n; i++)
    55     {
    56         z = read() + 1;
    57         x = query1(z + 1) + 1;
    58         y = query0(z - 1) + 1;
    59         update0(z, x);
    60         update1(z, y);
    61         ans = max(ans, max(x, y));
    62     }
    63     printf("%d
    ", ans);
    64     return 0;
    65 }
    View Code

    100分

    f[i][0] 表示第 i 个作为高的,的最优解

    f[i][0] 表示第 i 个作为低的,的最优解

    (然而第 i 个不一定选)

    那么

    h[i]>h[i1]时, 

    f[i][0]=max{f[i1][0],f[i1][1]+1},f[i][1]=f[i1][1]; 

    h[i]==h[i1]时, 

    f[i][0]=f[i1][0],f[i][1]=f[i1][1]; 

    h[i]<h[i1]时, 

    f[i][0]=f[i1][0],f[i][1]=max{f[i1][1],f[i1][0]+1}. 

    答案ans=max{f[n][0],f[n][1]}; 

    边界为f[1][0]=f[1][1]=1

    ——代码

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 const int MAXN = 100001, INF = ~(1 << 31);
     5 int n, ans;
     6 int a[MAXN], f[MAXN][2];
     7 
     8 inline int max(int x, int y)
     9 {
    10     return x > y ? x : y;
    11 }
    12 
    13 int main()
    14 {
    15     //freopen("flower.in", "r", stdin);
    16     //freopen("flower.out", "w", stdout);
    17     int i, j;
    18     scanf("%d", &n);
    19     for(i = 1; i <= n; i++) scanf("%d", &a[i]);
    20     f[1][0] = f[1][1] = 1;
    21     for(i = 2; i <= n; i++)
    22     {
    23         if(a[i] > a[i - 1])
    24         {
    25             f[i][0] = max(f[i - 1][0], f[i - 1][1] + 1);
    26             f[i][1] = f[i - 1][1];
    27         }
    28         else if(a[i] == a[i - 1])
    29         {
    30             f[i][0] = f[i - 1][0];
    31             f[i][1] = f[i - 1][1];
    32         }
    33         else
    34         {
    35             f[i][0] = f[i - 1][0];
    36             f[i][1] = max(f[i - 1][1], f[i - 1][0] + 1);
    37         }
    38     }
    39     printf("%d
    ", max(f[n][0], f[n][1]));
    40     return 0;
    41 }
    View Code
  • 相关阅读:
    Python环境搭建
    接口测试工具Jmeter
    接口测试工具postman
    fiddler -- 一个强大的抓包工具
    Pychram中使用reduce()函数报错:Unresolved reference 'reduce'
    Mac下用命令行获取苹果手机的UDID
    python 的 lambda使用笔记
    appium报错:An unknown server-side error occurred while processing the command. Original error: Could not proxy command to remote server. Original error: Error: read ECONNRESET
    Pycharm中使用from appium import webdriver时报错:ModuleNotFoundError: No module named 'appium'
    如何升级pip3
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6886144.html
Copyright © 2011-2022 走看看