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=4990

题面

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

输入

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.

输出

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

样例输入

6

1

2

3

4

5

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;
}
posted @   qscqesze  阅读(595)  评论(0编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥
点击右上角即可分享
微信分享提示