4990: [Usaco2017 Feb]Why Did the Cow Cross the Road II 线段树维护dp

题目 4990: [Usaco2017 Feb]Why Did the Cow Cross the Road II

连接

http://www.lydsy.com/JudgeOnline/problem.php?id=4990php

题面

上下有两个长度为n、位置对应的序列A、B,
其中数的范围均为1~n。若abs(A[i]-B[j]) <= 4,
则A[i]与B[j]间能够连一条边。现要求在边与边不相交的状况下的最大的连边数量。
n <= 10^5。node

输入

The first line of input contains N (1≤N≤100,0000).
The next N lines describe the order, by breed ID, of fields on one side of the road;
each breed ID is an integer in the range 1…N
The last N lines describe the order, by breed ID, of the fields on the other side of the road.
Each breed ID appears exactly once in each ordering.c++

输出

Please output the maximum number of disjoint "friendly crosswalks" Farmer John can draw across the road.app

样例输入

6ide

1优化

2ui

3spa

4code

5get

6

6

5

4

3

2

1

样例输出

5

题解

考虑二维dp[i][j]表示考虑到<a[i],b[j]>的最大数目
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
若是ai和bj可以链接,dp[i][j]=max(dp[i-1][j-1]+1)

显然第一维能够优化,而后用个线段树求前缀最大值便可。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int a[maxn],b[maxn],c[maxn],n,dp[maxn];
struct node{int l,r,x;}t[maxn*4];
void build(int x,int l,int r)
{
    t[x].l=l,t[x].r=r;
    if(l==r){t[x].x=0;return;}
    int mid=(l+r)/2;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    t[x].x=max(t[x<<1].x,t[x<<1|1].x);
}
void update(int x,int l,int r,int v){
    int L=t[x].l,R=t[x].r;
    if(l==L&&R==r){
        t[x].x=v;
        return;
    }
    int mid=(L+R)/2;
    if(mid>=l)update(x<<1,l,r,v);
    if(mid<r)update(x<<1|1,l,r,v);
    t[x].x=max(t[x<<1].x,t[x<<1|1].x);
}
int query(int x,int l,int r)
{
    int L=t[x].l,R=t[x].r;
    if(l<=L&&R<=r)return t[x].x;
    int ans=0,mid=(L+R)/2;
    if(mid>=l)ans=max(ans,query(x<<1,l,r));
    if(mid<r)ans=max(ans,query(x<<1|1,l,r));
    return ans;
}
int main(){
    scanf("%d",&n);
    build(1,1,n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&b[i]);
    }
    for(int i=1;i<=n;i++){
        c[b[i]]=i;
    }
    for(int i=1;i<=n;i++){
        for(int j=-4;j<=4;j++){
            if(a[i]+j>0&&a[i]+j<=n){
                dp[c[a[i]+j]]=max(dp[c[a[i]+j]],query(1,1,c[a[i]+j]-1)+1);
            }
        }
        for(int j=-4;j<=4;j++){
            if(a[i]+j>0&&a[i]+j<=n){
                update(1,c[a[i]+j],c[a[i]+j],dp[c[a[i]+j]]);
            }           
        }
    }
    cout<<query(1,1,n)<<endl;
}
相关文章
相关标签/搜索