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;
    }
  • 相关阅读:
    winform+c#之窗体之间的传值 Virus
    ASP.NET 2.0 利用 checkbox获得选中行的行号, 在footer中显示 Virus
    .NET中的winform的listview控件 Virus
    我的书橱
    Expert .NET 2.0 IL Assembler·译者序一 写在一稿完成之即
    Verbal Description of Custom Attribute Value
    AddressOfCallBacks in TLS
    下一阶段Schedule
    2008 Oct MVP OpenDay 第二天 博客园聚会
    2008 Oct MVP OpenDay 第二天 颁奖·讲座·晚会
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8076041.html
Copyright © 2011-2022 走看看