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