zoukankan      html  css  js  c++  java
  • BZOJ4553 [Tjoi2016&Heoi2016]序列

    这题我们可以联想为普通的最长上升子序列,既f[i]=max(f[j])+1;i>j

    所以这个就有了后效性,我们只关注他的左区间对答案的贡献,也就是j<=mid i>=mid+1;

    所以顺序就变为了左边,中间,右边

    By:大奕哥

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=100005;
     4 int n,m;
     5 struct node
     6 {
     7     int l,r,id,a;
     8     bool operator <(const node &b)const{
     9         if(l==b.l)
    10         {
    11             return r==b.r?id<b.id:r<b.r;
    12         }
    13         return l<b.l;
    14     }
    15 }q[N],p[N];
    16 int t[N],v[N],tim,f[N];
    17 inline int lowbit(int x){return x&(-x);}
    18 void add(int x,int y)
    19 {
    20     for(;x<=N-5;x+=lowbit(x))
    21     {
    22         if(v[x]!=tim)
    23         {
    24             v[x]=tim;t[x]=y;
    25         }
    26         else t[x]=max(t[x],y);
    27     }
    28 }
    29 int get(int x)
    30 {
    31     int an=0;for(;x;x-=lowbit(x))if(tim==v[x])an=max(an,t[x]);return an;
    32 }
    33 void solve(int l,int r)
    34 {
    35     if(l==r){f[l]=max(f[l],1);return;}
    36     int mid=l+r>>1;
    37     solve(l,mid);tim++;
    38     for(int i=l;i<=r;++i)
    39     {
    40         if(i<=mid)p[i].l=q[i].a,p[i].r=q[i].r,p[i].id=q[i].id;
    41         else p[i].l=q[i].l,p[i].r=q[i].a,p[i].id=q[i].id;
    42     }
    43     sort(p+l,p+r+1);
    44     for(int i=l;i<=r;++i)
    45     {
    46         if(p[i].id<=mid)add(p[i].r,f[p[i].id]);
    47         else f[p[i].id]=max(f[p[i].id],get(p[i].r)+1);
    48     }
    49     solve(mid+1,r);
    50 }
    51 int main()
    52 {
    53     scanf("%d%d",&n,&m);int x,y;
    54     for(int i=1;i<=n;++i)scanf("%d",&q[i].a),q[i].r=q[i].l=q[i].a,q[i].id=i;
    55     for(int i=1;i<=m;++i)
    56     {
    57         scanf("%d%d",&x,&y);q[x].r=max(q[x].r,y);q[x].l=min(q[x].l,y);
    58     }
    59     solve(1,n);int ans=0;
    60     for(int i=1;i<=n;++i)ans=max(ans,f[i]);
    61     printf("%d
    ",ans);
    62     return 0;
    63 }

     LIS的dp很简单,三维偏序,max[j]<a[i]  a[j]<min[i]  j<i  我们分治一下,然后两边排一下序,左面按a[j]排序,右面按min[i] 排序,这样我们可以满足两维,接下俩用线段树做一下第三个偏序即可。—— by VANE

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    int t[N*4],a[N],id[N],mi[N],mx[N],f[N];
    bool bz[N*4];
    int n,m,ans;
    void clear(int p)
    {
        t[p]=0;bz[p]=1;
    }
    void pushdown(int p)
    {
        if(bz[p])
        {
            clear(p<<1);
            clear(p<<1|1);
            bz[p]=0;
        }
    }
    void change(int p,int l,int r,int a,int b)
    {
        if(l==r)
        {
            t[p]=max(t[p],b);
            return;
        }
        pushdown(p);
        int mid=l+r>>1;
        if(a<=mid) change(p<<1,l,mid,a,b);
        else change(p<<1|1,mid+1,r,a,b);
        t[p]=max(t[p<<1],t[p<<1|1]);
    }
    int query(int p,int l,int r,int a,int b)
    {
        
        if(l==a&&r==b) return t[p];
        pushdown(p);
        int mid=l+r>>1;
        if(b<=mid) return query(p<<1,l,mid,a,b);
        else if(a>mid) return query(p<<1|1,mid+1,r,a,b);
        else return max(query(p<<1,l,mid,a,mid),query(p<<1|1,mid+1,r,mid+1,b));
    }
    bool cmpa(int x,int y)
    {
        return a[x]<a[y];
    }
    bool cmpmi(int x,int y)
    {
        return mi[x]<mi[y];
    }
    void solve(int l,int r)
    {
        if(l==r)
        {
            f[l]=max(f[l],1);
            return;
        }
        int mid=l+r>>1;
        solve(l,mid);
        for(int i=l;i<=r;++i) id[i]=i;
        sort(id+l,id+1+mid,cmpa);
        sort(id+mid+1,id+r+1,cmpmi);
        clear(1);
        int j=l,i;
        for(i=mid+1;i<=r;++i)
        {
            while(j<=mid&&a[id[j]]<=mi[id[i]])
            {
                change(1,1,n,mx[id[j]],f[id[j]]);
                j++;
                
            }
            f[id[i]]=max(f[id[i]],query(1,1,n,1,a[id[i]])+1);
        }
        solve(mid+1,r);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",a+i),mi[i]=mx[i]=a[i];
        for(int i=1;i<=m;++i)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            mi[x]=min(mi[x],y);
            mx[x]=max(mx[x],y);
        }
        solve(1,n);
        int ans=0;
        for(int i=1;i<=n;++i) ans=max(ans,f[i]);
        cout<<ans;
    }
  • 相关阅读:
    [Windows Server 2003] 服务器安全加固
    [Windows Server 2008] 手工创建安全网站
    [Windows Server 2008] 服务器安全加固
    [Windows Server 2008] Apache+PHP安全设置
    [Windows Server 2008] DEDECMS(织梦)安全设置
    [Windows Server 2008] Serv-U安全设置
    [Windows Server 2008] Ecshop安全设置
    [Windows Server 2012] 手工创建安全网站
    [Windows Server 2012] 服务器安全加固
    [Windows Server 2012] Apache+PHP安全设置
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8076041.html
Copyright © 2011-2022 走看看