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\n",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;
}

 

posted @ 2017-12-20 21:55  大奕哥&VANE  阅读(202)  评论(0编辑  收藏  举报