zoukankan      html  css  js  c++  java
  • [补档][Poi2010]Monotonicity 2

    [Poi2010]Monotonicity 2

    题目

    给出N个正整数a[1..N],再给出K个关系符号(>、<或=)s[1..k]。
    选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1]。
    求出L的最大值。

    INPUT

    第一行两个正整数,分别表示N和K (N, K <= 500,000)。
    第二行给出N个正整数,第i个正整数表示a[i] (a[i] <= 10^6)。
    第三行给出K个空格隔开关系符号(>、<或=),第i个表示s[i]。

    OUTPUT

    一个正整数,表示L的最大值。

    SAMPLE

    INPUT

    7 3
    2 4 3 1 3 5 3
    < > =

    OUTPUT

    6

    解题报告

    考试时连最最最简单的DP都没想出来,就打了个DFS- -
    正解:
    我们先考虑只有一种符号的情况,比如说考虑<,那么不就变成了求最长上升子序列吗。
    同样的,我们扩展至三种符号:
     1 for(int i=1;i<=n;i++){
     2     f[i]=1;
     3     for(int j=1;j<=i-1;j++){
     4         int tmp(f[j]%k+1);
     5         if(op[tmp]=='='&&a[j]==a[i]&&f[j]+1>f[i])
     6             f[i]=f[j]+1;
     7         if(op[tmp]=='>'&&a[j]>a[i]&&f[j]+1>f[i])
     8             f[i]=f[j]+1;
     9         if(op[tmp]=='<'&&a[j]<a[i]&&f[j]+1>f[i])
    10             f[i]=f[j]+1;
    11     }
    12 }
    View Code
    这就是最最最简单的DP,然而我们知道,这玩意是O(n²)的复杂度,显然会T,那么我们就需要优化一下了。
    我们发现,转移时有O(n)的复杂度来找最大值,那么我们想,是否可以把这个过程优化呢?自然可以,我们的目的在于找到权值符合条件的最大f值,所以,我们需要一个新的东西来完成它:

    权值线段树

    这是一个神奇的数据结构- -,好吧,也不怎么神奇,它在这道题里是以权值为下标,存入该点最优解的一种线段树,它就可以完成这个伟大的任务啦。
    我们需要3棵树(其实2棵也可以,相等的那个用数组模拟即可实现,只是我比较懒- -),每一棵树存以该符号为后面所接符号的权值的最优解(好绕啊- -),这样我们在找的时候,取出每棵树中符合权值条件的最优解,三解进行比较,选出最优以确定符号,继续转移并更新相应的线段树即可。
    (我语文表达能力好弱啊)
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 using namespace std;
      5 inline int read(){
      6     int sum(0);
      7     char ch(getchar());
      8     for(;ch<'0'||ch>'9';ch=getchar());
      9     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
     10     return sum;
     11 }
     12 inline char init(){
     13     char ch(getchar());
     14     for(;ch!='='&&ch!='>'&&ch!='<';ch=getchar());
     15     return ch;
     16 }
     17 inline int my_max(int a,int b){
     18     return a>b?a:b;
     19 }
     20 int n,k;
     21 int a[500001],op[500001];
     22 int tr_d[4000001],tr_x[4000001],tr_e[4000001];
     23 int ad_d[4000001],ad_x[4000001],ad_e[4000001];
     24 inline void pushup_d(int i){
     25     tr_d[i]=my_max(tr_d[i<<1],tr_d[i<<1|1]);
     26 }
     27 inline void pushup_x(int i){
     28     tr_x[i]=my_max(tr_x[i<<1],tr_x[i<<1|1]);
     29 }
     30 inline void pushup_e(int i){
     31     tr_e[i]=my_max(tr_e[i<<1],tr_e[i<<1|1]);
     32 }
     33 inline void pushdown_d(int i){
     34     if(ad_d[i]){
     35         ad_d[i<<1]=ad_d[i];
     36         ad_d[i<<1|1]=ad_d[i];
     37         tr_d[i<<1]=ad_d[i];
     38         tr_d[i<<1|1]=ad_d[i];
     39         tr_d[i]=ad_d[i];
     40         ad_d[i]=0;
     41     }
     42 }
     43 inline void pushdown_x(int i){
     44     if(ad_x[i]){
     45         ad_x[i<<1]=ad_x[i];
     46         ad_x[i<<1|1]=ad_x[i];
     47         tr_x[i<<1]=ad_x[i];
     48         tr_x[i<<1|1]=ad_x[i];
     49         tr_x[i]=ad_x[i];
     50         ad_x[i]=0;
     51     }
     52 }
     53 inline void pushdown_e(int i){
     54     if(ad_e[i]){
     55         ad_e[i<<1]=ad_e[i];
     56         ad_e[i<<1|1]=ad_e[i];
     57         tr_e[i<<1]=ad_e[i];
     58         tr_e[i<<1|1]=ad_e[i];
     59         tr_e[i]=ad_e[i];
     60         ad_e[i]=0;
     61     }
     62 }
     63 inline void update_d(int ll,int rr,int c,int l,int r,int i){
     64     if(ll<=l&&r<=rr){
     65         ad_d[i]=c;
     66         tr_d[i]=c;
     67         return;
     68     }
     69     pushdown_d(i);
     70     int mid((l+r)>>1);
     71     if(ll<=mid)
     72         update_d(ll,rr,c,l,mid,i<<1);
     73     if(rr>mid)
     74         update_d(ll,rr,c,mid+1,r,i<<1|1);
     75     pushup_d(i);
     76 }
     77 inline void update_x(int ll,int rr,int c,int l,int r,int i){
     78     if(ll<=l&&r<=rr){
     79         ad_x[i]=c;
     80         tr_x[i]=c;
     81         return;
     82     }
     83     pushdown_x(i);
     84     int mid((l+r)>>1);
     85     if(ll<=mid)
     86         update_x(ll,rr,c,l,mid,i<<1);
     87     if(rr>mid)
     88         update_x(ll,rr,c,mid+1,r,i<<1|1);
     89     pushup_x(i);
     90 }
     91 inline void update_e(int ll,int rr,int c,int l,int r,int i){
     92     if(ll<=l&&r<=rr){
     93         ad_e[i]=c;
     94         tr_e[i]=c;
     95         return;
     96     }
     97     pushdown_e(i);  
     98     int mid((l+r)>>1);
     99     if(ll<=mid)
    100         update_e(ll,rr,c,l,mid,i<<1);
    101     if(rr>mid)
    102         update_e(ll,rr,c,mid+1,r,i<<1|1);
    103     pushup_e(i);
    104 }
    105 inline int query_d(int ll,int rr,int l,int r,int i){
    106     if(ll>rr)
    107         return 0;
    108     if(ll<=l&&r<=rr)
    109         return tr_d[i];
    110     pushdown_d(i);
    111     int mid((l+r)>>1);
    112     int ret(0);
    113     if(ll<=mid)
    114         ret=my_max(ret,query_d(ll,rr,l,mid,i<<1));
    115     if(rr>mid)
    116         ret=my_max(ret,query_d(ll,rr,mid+1,r,i<<1|1));
    117     return ret;
    118 }
    119 inline int query_x(int ll,int rr,int l,int r,int i){
    120     if(ll>rr)
    121         return 0;
    122     if(ll<=l&&r<=rr)
    123         return tr_x[i];
    124     pushdown_x(i);  
    125     int mid((l+r)>>1);
    126     int ret(0);
    127     if(ll<=mid)
    128         ret=my_max(ret,query_x(ll,rr,l,mid,i<<1));
    129     if(rr>mid)
    130         ret=my_max(ret,query_x(ll,rr,mid+1,r,i<<1|1));
    131     return ret;
    132 }
    133 inline int query_e(int ll,int rr,int l,int r,int i){
    134     if(ll>rr)
    135         return 0;
    136     if(ll<=l&&r<=rr)
    137         return tr_e[i];
    138     pushdown_e(i);
    139     int mid((l+r)>>1);
    140     int ret(0);
    141     if(ll<=mid)
    142         ret=my_max(ret,query_e(ll,rr,l,mid,i<<1));
    143     if(rr>mid)
    144         ret=my_max(ret,query_e(ll,rr,mid+1,r,i<<1|1));
    145     return ret;
    146 }
    147 int f[500001];
    148 int mx(0);
    149 int main(){
    150     n=read(),k=read();
    151     for(int i=1;i<=n;i++)
    152         a[i]=read(),mx=my_max(mx,a[i]);
    153     for(int i=1;i<=k;i++){
    154         char ch(init());
    155         if(ch=='>')
    156             op[i]=1;
    157         if(ch=='<')
    158             op[i]=2;
    159         if(ch=='=')
    160             op[i]=3;
    161     }
    162     f[1]=1;
    163     if(op[1]==1)
    164         update_d(a[1],a[1],f[1],1,mx,1);
    165     if(op[1]==2)
    166         update_x(a[1],a[1],f[1],1,mx,1);
    167     if(op[1]==3)
    168         update_e(a[1],a[1],f[1],1,mx,1);
    169     for(int i=2;i<=n;i++){
    170         int now(a[i]);
    171         int ans_d(query_d(now+1,mx,1,mx,1));
    172         int ans_x(query_x(1,now-1,1,mx,1));
    173         int ans_e(query_e(now,now,1,mx,1));
    174         int ans(my_max(my_max(ans_d,ans_x),ans_e));
    175         f[i]=ans+1;
    176         int o(op[ans%k+1]);//cout<<i<<' '<<f[i]<<' '<<o<<endl;
    177         if(o==1)
    178             update_d(now,now,f[i],1,mx,1);
    179         if(o==2)
    180             update_x(now,now,f[i],1,mx,1);
    181         if(o==3)
    182             update_e(now,now,f[i],1,mx,1);
    183     }
    184     int mxx(0);
    185     for(int i=1;i<=n;i++)
    186         mxx=my_max(mxx,f[i]);
    187     printf("%d",mxx);
    188 }
    View Code
    写的极其丑- -,毕竟三颗线段树乱搞
    凑合着看吧,其实理解了之后,一颗线段树,加不同的域,对传的参数进行处理,就可以达到三颗线段树的效果
  • 相关阅读:
    BZOJ 4802 欧拉函数(Pollard_Rho)
    Codeforces 804E The same permutation(构造)
    Codeforces 804D Expected diameter of a tree(树形DP+期望)
    BZOJ 3399 [Usaco2009 Mar]Sand Castle城堡(贪心)
    BZOJ 2430 [Poi2003]Chocolate(贪心+归并排序)
    BZOJ 1707 [Usaco2007 Nov]tanning分配防晒霜(扫描线+贪心+优先队列)
    BZOJ 1828 [Usaco2010 Mar]balloc 农场分配(贪心+线段树)
    BZOJ 1827 [Usaco2010 Mar]gather 奶牛大集会(树形DP)
    BZOJ 2697 特技飞行(贪心)
    BZOJ 4883 [Lydsy2017年5月月赛]棋盘上的守卫(最小生成环套树森林)
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7276902.html
Copyright © 2011-2022 走看看