zoukankan      html  css  js  c++  java
  • P3928 SAC E#1

    题目背景

    小强和阿米巴是好朋友。

    题目描述

    小强喜欢数列。有一天,他心血来潮,写下了三个长度均为n的数列。

    阿米巴也很喜欢数列。但是他只喜欢其中一种,波动数列。

    阿米巴把他的喜好告诉了小强。小强便打算找出这三个数列内的最长波动数列。

    也就是说,如果我们将三个数列记做a[n][3],他必须要构造一个二元组序列:<p[i], q[i]>,使得对于任何 i>1 有:

    p[i] > p[i-1]

    若q[i] = 0,a[p[i]][q[i]] >= a[p[i-1]][q[i-1]]

    若q[i] = 1,a[p[i]][q[i]] <= a[p[i-1]][q[i-1]]

    若q[i] = 2,只要保持段内同向即可(就是对于连续的一段q[i]=2,要么都有a[p[i]][q[i]] >= a[p[i-1]][q[i-1]],要么都有a[p[i]][q[i]] <= a[p[i-1]][q[i-1]])。

    小强希望这个二元组序列尽可能长。

    提示:当q[i] != q[i-1]时,数列的增减性由q[i]而非q[i-1]决定。

    清晰版题目描述

    小强拿到一个3×n的数组,要在每一列选一个数(或者不选),满足以下条件:

    1.如果在第一行选,那它必须大于等于上一个数

    2.如果在第二行选,那么必须小于等于上一个数

    3.如果在第三行选,对于连续的一段在第三行选的数,必须满足方向相同(都小于等于上一个数或者都大于等于上一个数)

    输入输出格式

    输入格式:

    输入包含4行。

    第一行一个数n,表示数列长度。

    第2、3、4行,每行n个整数,分别表示三个数列。

    输出格式:

    输出仅包含一个整数,即最长波动数列的长度。

    输入输出样例

    输入样例#1:
    6
    1 2 3 6 5 4
    5 4 3 7 8 9
    1 2 3 6 5 4
    
    输出样例#1:
    6

    说明

    对于20%的数据,n <= 10, m <= 1000

    对于60%的数据,n <= 1000, m <= 1000

    对于100%的数据, n <= 100000, m <= 1000000000

    其中m = max|a[i]|

    样例解释:

    取第三行1 2 3(增),然后取第1行6(增),然后取第三行5 4(减),长度为6。

    我们考虑dp

    f[i][1]表示第i位,选第1行

    f[i][2]表示选第2行

    f[i][3/4]表示第i位,选第3行,比上一个大/小

    满足条件下:

    f[i][1]=max(f[j][1~4])

    f[i][2]=max(f[j][1~4])

    f[i][3]=max(f[j][1,2,3])

    f[i][4]=max(f[j][1,2,4])

    这样时间复杂度为n^2

    用线段树优化至nlogn

    把所有a值离散,对应于4颗线段树

    转移就变成了区间查询最大值,单点修改

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 int c[3200001][5],n,sz,a[200001][5],b[1000001],num;
     7 int f[200001][5],s1,s2,s3,s4,ans;
     8 void pushup(int rt,int p)
     9 {
    10     c[rt][p]=max(c[rt*2][p],c[rt*2+1][p]);
    11 }
    12 int query(int rt,int l,int r,int L,int R,int p)
    13 {
    14     if (l>=L&&r<=R)
    15     {
    16         return c[rt][p];
    17     }
    18     int mid=(l+r)/2,s=0;
    19     if (L<=mid) s=max(s,query(rt*2,l,mid,L,R,p));
    20     if (R>mid) s=max(s,query(rt*2+1,mid+1,r,L,R,p));
    21     return s;
    22 }
    23 void update(int rt,int l,int r,int x,int d,int p)
    24 {
    25     if (l==r)
    26     {
    27         c[rt][p]=d;
    28         return;
    29     }
    30     int mid=(l+r)/2;
    31     if (x<=mid) update(rt*2,l,mid,x,d,p);
    32     else update(rt*2+1,mid+1,r,x,d,p);
    33     pushup(rt,p);
    34 }
    35 int main()
    36 {
    37     int i,j;
    38     cin>>n;
    39     for (j=1; j<=3; j++)
    40     {
    41         for (i=1; i<=n; i++)
    42         {
    43             scanf("%d",&a[i][j]);
    44             num++;
    45             b[num]=a[i][j];
    46         }
    47     }
    48     sort(b+1,b+num+1);
    49     sz=unique(b+1,b+num+1)-(b+1);
    50     for (j=1; j<=3; j++)
    51     {
    52         for (i=1; i<=n; i++)
    53             a[i][j]=lower_bound(b+1,b+sz+1,a[i][j])-b;
    54     }
    55     for (i=1; i<=n; i++)
    56         a[i][4]=a[i][3];
    57     for (i=1; i<=n; i++)
    58     {
    59         s1=query(1,1,sz,1,a[i][1],1);
    60         s2=query(1,1,sz,1,a[i][1],2);
    61         s3=query(1,1,sz,1,a[i][1],3);
    62         s4=query(1,1,sz,1,a[i][1],4);
    63         f[i][1]=max(f[i][1],1+max(s1,max(s2,max(s3,s4))));
    64 
    65         s1=query(1,1,sz,a[i][2],sz,1);
    66         s2=query(1,1,sz,a[i][2],sz,2);
    67         s3=query(1,1,sz,a[i][2],sz,3);
    68         s4=query(1,1,sz,a[i][2],sz,4);
    69         f[i][2]=max(f[i][2],1+max(s1,max(s2,max(s3,s4))));
    70 
    71         s1=query(1,1,sz,1,a[i][3],1);
    72         s2=query(1,1,sz,1,a[i][3],2);
    73         s3=query(1,1,sz,1,a[i][3],3);
    74         f[i][3]=max(f[i][3],1+max(s1,max(s2,s3)));
    75 
    76         s1=query(1,1,sz,a[i][4],sz,1);
    77         s2=query(1,1,sz,a[i][4],sz,2);
    78         s4=query(1,1,sz,a[i][4],sz,4);
    79         f[i][4]=max(f[i][4],1+max(s1,max(s2,s4)));
    80 
    81         update(1,1,sz,a[i][1],f[i][1],1);
    82         update(1,1,sz,a[i][2],f[i][2],2);
    83         update(1,1,sz,a[i][3],f[i][3],3);
    84         update(1,1,sz,a[i][4],f[i][4],4);
    85         ans=max(ans,max(f[i][1],max(f[i][2],max(f[i][3],f[i][4]))));
    86     }
    87     cout<<ans;
    88 }
  • 相关阅读:
    ACM: Copying Data 线段树-成段更新-解题报告
    POJ 2488 A Knight's Journey
    POJ 3349 Snowflake Snow Snowflakes Hash
    POJ 2299 Ultra-QuickSort 归并排序、二叉排序树,求逆序数
    POJ 1035 Spell checker 简单字符串匹配
    POJ 3267 The Cow Lexicon 简单DP
    POJ 1459 Power Network 最大流(Edmonds_Karp算法)
    POJ 3687 Labeling Balls 逆向建图,拓扑排序
    HDU 1532 Drainage Ditches 最大流 (Edmonds_Karp)
    POJ 3026 Borg Maze bfs+Kruskal
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7635407.html
Copyright © 2011-2022 走看看