• [bzoj4553]序列


    记第i个位置有三个属性:1.ai表示原来的值;2.bi表示变成最大的值;3.ci表示变成最小的值。那么对于如果i在j的前面,那么必然有:$ai\le cj$且$bi\le aj$,那么令f[i]表示以i为结尾的最长上升子序列,即对求max(f[j])满足j能在i的前面,用树套树维护即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005 
     4 #define mid (l+r>>1)
     5 int V,n,m,x,y,ans,a[N],b[N],c[N],ro[N*200],f[N*200],ls[N*200],rs[N*200];
     6 void update(int &k,int l,int r,int x,int y,int z){
     7     if (!k)k=++V;
     8     if (y)update(ro[k],1,N-5,y,0,z);
     9     if (l==r){
    10         f[k]=max(f[k],z);
    11         return;
    12     }
    13     if (x<=mid)update(ls[k],l,mid,x,y,z);
    14     else update(rs[k],mid+1,r,x,y,z);
    15     f[k]=max(f[ls[k]],f[rs[k]]);
    16 }
    17 int query(int k,int l,int r,int x,int y,int x2,int y2){
    18     if ((!k)||(l>y)||(x>r))return 0;
    19     if ((x<=l)&&(r<=y))
    20         if (x2)return query(ro[k],1,N-5,x2,y2,0,0);
    21         else return f[k];
    22     return max(query(ls[k],l,mid,x,y,x2,y2),query(rs[k],mid+1,r,x,y,x2,y2));
    23 }
    24 int main(){
    25     scanf("%d%d",&n,&m);
    26     for(int i=1;i<=n;i++){
    27         scanf("%d",&a[i]);
    28         b[i]=c[i]=a[i];
    29     }
    30     for(int i=1;i<=m;i++){
    31         scanf("%d%d",&x,&y);
    32         b[x]=max(b[x],y);
    33         c[x]=min(c[x],y);
    34     }
    35     update(x=0,1,N-5,a[1],b[1],1);
    36     for(int i=2;i<=n;i++){
    37         int s=query(1,1,N-5,1,c[i],1,a[i])+1;
    38         update(x,1,N-5,a[i],b[i],s);
    39         ans=max(ans,s);
    40     }
    41     printf("%d\n",ans);
    42 }
    View Code
  • 相关阅读:
    #454. 【UER #8】打雪仗
    6496. 【GDOI2020模拟03.08】圣痕
    6495. 【GDOI2020模拟03.08】死星
    6494. 【GDOI2020模拟03.08】勘探
    NOI Online划水记
    6482. 【GDOI2020模拟02.22】代数几何(algebraic)
    6493. 【GDOI2020模拟03.04】迷宫
    6492. 【GDOI2020模拟03.04】多项式
    6491. 【GDOI2020模拟03.04】铺路
    #76. 【UR #6】懒癌
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11272801.html
Copyright © 2020-2023  润新知