• Codeforces Round #345 Div.1 D.Zip-line 动态最长上升子序列


    题意概述:

    给出一个长度为N的序列和M组询问,问假设把某个位置的值改成另一个给出的值之后,序列的最长上升子序列的长度。

    N,M<=400000.

    分析:

    考虑某个位置的值改动后这个位置和最长上升子序列(lis)的关系:

    1、这个位置包含在lis中(这种情况答案可能+1,可计算经过这个点的lis来等效决策)。

    2、这个位置不包含在lis中,那么需要看是否任意的lis都经过这个位置。如果是的话此决策的结果在原来长度基础上-1,否则就等于原来的长度。

    有了大体思路,接下来想想维护。

    任务1:对于任意位置x,求包含这个点的lis长度,令g1(i)表示1->N方向长度为i的lis的最长上升子序列的最后一个值的最小值,g2(i)表示N->1方向长度为i的最长下降子序列的最后一个值的最大值(更新就不说了,基础),如果知道位置x状态下恰好未更新的g1,g2数组内容,就同更新一样用前后以这个点结尾的最长序列长度相加-1就是此决策的结果。

    任务2:这个实际上是重点,对于任意位置x,知道的东西和任务1一样,同时知道是否存在一对g1(a),g2(b)满足a+b=len(len是原序列lis长度)&&g1(a)<g2(b),如果存在那么此决策的结果为原来答案,否则为原来答案-1。

    如果要强行在线的话三棵主席树维护一下两个g数组和一个vis数组(vis(x)表示对于当前状态来说g1(x),g2(len-x)是否合法,当前状态是否合法实际上就是看vis的所有值的和是否不为0)然后随便乱搞就可以了。

    然而。。。我选择离线,询问按照位置排序,正反扫一遍序列处理第一种情况,然后再正着扫一遍把第二种情况用一个数组处理了就可以了。能离线何苦去在线码主席树呢(手动滑稽)(手动链表或者vector都可以帮忙离线)?!!

    然而我还是弄了半天,污浊的机房CO2,QAQ

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #include<set>
     9 #include<map>
    10 #include<vector>
    11 #include<cctype>
    12 using namespace std;
    13 const int maxn=400005;
    14 
    15 int N,M,h[maxn];
    16 struct que{
    17     int id,pos,v;
    18     friend bool operator < (que a,que b){
    19         return a.pos<b.pos;
    20     }
    21 }q[maxn];
    22 int g1[maxn],g2[maxn],cnt1,cnt2,ans[maxn],len,vis[maxn];
    23 struct mlink{
    24     static const int max_sz=400005;
    25     int np,w[maxn],first[maxn],next[maxn];
    26     mlink(){
    27         np=0,w[0]=next[0]=0;
    28         memset(first,0,sizeof(first));
    29     }
    30     void ins(int i,int x) { w[++np]=x,next[np]=first[i],first[i]=np; }
    31     void del(int i) { first[i]=next[first[i]]; }
    32     int val(int i) { return w[first[i]]; }
    33 }dd;
    34 
    35 void data_in()
    36 {
    37     scanf("%d%d",&N,&M);
    38     for(int i=1;i<=N;i++) scanf("%d",&h[i]);
    39     for(int i=1;i<=M;i++){
    40         scanf("%d%d",&q[i].pos,&q[i].v);
    41         q[i].id=i;
    42     } 
    43     sort(q+1,q+M+1);
    44 }
    45 bool cmp(int x,int y) { return x>y; }
    46 void work()
    47 {
    48     for(int i=1;i<=N;i++){
    49         int j=lower_bound(q+1,q+M+1,(que){0,i,0})-q;
    50         while(j<=M&&q[j].pos==i)
    51             ans[q[j].id]=lower_bound(g1+1,g1+cnt1+1,q[j].v)-g1,j++;
    52         int x=lower_bound(g1+1,g1+cnt1+1,h[i])-g1;
    53         if(x>cnt1) cnt1=x;
    54         g1[x]=h[i];
    55     }
    56     for(int i=N;i>=1;i--){
    57         int j=lower_bound(q+1,q+M+1,(que){0,i,0})-q;
    58         while(j<=M&&q[j].pos==i)
    59             ans[q[j].id]+=lower_bound(g2+1,g2+cnt2+1,q[j].v,cmp)-g2-1,j++;
    60         int x=lower_bound(g2+1,g2+cnt2+1,h[i],cmp)-g2;
    61         if(x>cnt2) cnt2=x;
    62         g2[x]=h[i];
    63         dd.ins(x,g2[x]);
    64     }
    65     memset(g1,0,sizeof(g1)); len=cnt1,cnt1=0;
    66     int x=lower_bound(g2+1,g2+cnt2+1,h[1],cmp)-g2,sum=0;
    67     dd.del(x); g2[x]=dd.val(x);
    68     if(g2[len]) vis[0]=1,sum++;
    69     for(int i=1;i<=N;i++){
    70         int j=lower_bound(q+1,q+M+1,(que){0,i,0})-q;
    71         while(j<=M&&q[j].pos==i)
    72             ans[q[j].id]=max(ans[q[j].id],len-(sum==0)),j++;
    73         int x1=lower_bound(g1+1,g1+cnt1+1,h[i])-g1;
    74         if(x1>cnt1) cnt1=x1; g1[x1]=h[i];
    75         int x2=lower_bound(g2+1,g2+cnt2+1,h[i+1],cmp)-g2;
    76         dd.del(x2); g2[x2]=dd.val(x2);
    77         if(!g2[x2]) cnt2--;
    78         if((x1==len||g1[x1]<g2[len-x1])&&!vis[x1]) vis[x1]=1,sum++;//请注意这一句的第一个条件
    79         if(g1[len-x2]>=g2[x2]&&vis[len-x2]) vis[len-x2]=0,sum--;
    80     }
    81     for(int i=1;i<=M;i++) printf("%d
    ",ans[i]);
    82 }
    83 int main()
    84 {
    85     data_in();
    86     work();
    87     return 0;
    88 }
  • 相关阅读:
    0:一种过滤机制的MobileMenuList
    MobileMenuImage
    (转)How To Kill runaway processes After Terminating Concurrent Request
    fnd_profile.value('AFLOG_ENABLED')的取值 和配置文件相关SQL
    供应商 银行 SQL (转自ITPUB)
    重启并发管理器
    定义并发请求时 业务实体值集显示没有值数据
    Oracle EBS环境下查找数据源(OAF篇)
    查看在线EBS用户的相关信息
    转,Oracle中关于处理小数点位数的几个函数,取小数位数,Oracle查询函数
  • 原文地址:https://www.cnblogs.com/KKKorange/p/8463371.html
Copyright © 2020-2023  润新知