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; }