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;
}
相關文章
相關標籤/搜索