hdu 6076 Security Check

  OvO http://acm.hdu.edu.cn/showproblem.php?pid=6076

  2017 Multi-University Training Contest - Team 4 - 1010

  O(n2)的DP的话,

  第二种情况,dp[i][j]=max(max(dp[i][j-1],dp[i-1][j])+1,dp[i-1][j-1]+1),这种情况下dp[i][j]是必然取dp[i-1][j-1]+1的,

  这样对于dp[n][n]就可以类似贪心地处理,每次搜索碰到第二种情况优先取第二种情况,否则就取第一种的最大值。

  而在第一种状况下,因为k很小,所以要搜索的状态其实是很少的。

  对于第二种状况,拿一个向量记录每条对角线上不符合状况二的情况,这样每次搜到第二种情况都可以跳跃着搜索,(在起跳点所在的这条对角线的向量上,对跳跃的落脚点进行二分)。

  这样总的情况其实是很少的,可以加一个记忆化

  (思路来源于 1,2,3

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>

using namespace std;

typedef long long ll;

const int M=6e4+44;
const int bas=M-22;

int n,k;
int A[M],B[M],plcb[M];
map<int,map<int,int> > mp; //saves for case 1,case 2
vector<int> dia[M*2]; //diagonals saves

void init()
{
	mp.clear();
	int i,j,valb,pb;
	for(i=1-n;i<=n-1;i++)
		dia[i+bas].clear();
	for(i=1;i<=n;i++)
		for(j=0;j<=k;j++)
		{
			valb=A[i]-j;
			if(valb>0)
			{
				pb=plcb[valb];
				dia[i-pb+bas].push_back(i);
			}
			valb=A[i]+j;
			if(valb<=n)
			{
				pb=plcb[valb];
				dia[i-pb+bas].push_back(i);
			}
		}
	for(i=1-n;i<=n-1;i++)
		sort(dia[i+bas].begin(),dia[i+bas].end());
}

int deal(int wh,int now)
{
	int i,j,li,ri,mid;
	if(dia[wh].size()==0 || dia[wh][0]>now)
		return now-min(now,now-(wh-bas));
	li=0; ri=dia[wh].size();
	while(li<ri-1)
	{
		mid=(li+ri)>>1;
		if(dia[wh][mid]<now)
			li=mid;
		else
			ri=mid;
	}
	return dia[wh][li];
}

int dfs(int x,int y)
{
	int i,j,tmp,ret,val1,val2;
	if(x==0 || y==0)
		return x+y;
	if(abs(A[x]-B[y])<=k)
	{
		val1=mp[x-1][y];
		if(val1==0) val1=dfs(x-1,y);
		val2=mp[x][y-1];
		if(val2==0) val2=dfs(x,y-1);
		ret=1+min(val1,val2);
		mp[x][y]=ret;
		return ret;
	}
	else
	{
		tmp=x-deal(x-y+bas,x);
		ret=tmp+dfs(x-tmp,y-tmp);
		mp[x][y]=ret;
		return ret;
	}
}

int main()
{
//	freopen("数据\\1010.in","r",stdin);
//	freopen("数据\\fxxl1010.out","w",stdout);
	int i,j;
	int cas;
	scanf("%d",&cas);
	while(cas--)
	{
		scanf("%d%d",&n,&k);
		for(i=1;i<=n;i++)
			scanf("%d",&A[i]);
		for(i=1;i<=n;i++)
		{
			scanf("%d",&B[i]);
			plcb[B[i]]=i;
		}
		init();
		int ans=dfs(n,n);
		printf("%d\n",ans);
	}
	return 0;
}

  

 

posted @ 2017-08-07 19:58  太阳星人FxxL  阅读(242)  评论(6编辑  收藏  举报