Educational Codeforces Round 105 (Rated for Div. 2) C. 1D Sokoban(思维 二分)

题目链接:https://codeforc.es/contest/1494/problem/C

You are playing a game similar to Sokoban on an infinite number line. The game is discrete, so you only consider integer positions on the line.

You start on a position 0. There are n boxes, the i-th box is on a position ai. All positions of the boxes are distinct. There are also m special positions, the j-th position is bj. All the special positions are also distinct.

In one move you can go one position to the left or to the right. If there is a box in the direction of your move, then you push the box to the next position in that direction. If the next position is taken by another box, then that box is also pushed to the next position, and so on. You can’t go through the boxes. You can’t pull the boxes towards you.

You are allowed to perform any number of moves (possibly, zero). Your goal is to place as many boxes on special positions as possible. Note that some boxes can be initially placed on special positions.

Input
The first line contains a single integer t (1≤t≤1000) — the number of testcases.

Then descriptions of t testcases follow.

The first line of each testcase contains two integers n and m (1≤n,m≤2⋅105) — the number of boxes and the number of special positions, respectively.

The second line of each testcase contains n distinct integers in the increasing order a1,a2,…,an (−109≤a1<a2<⋯<an≤109; ai≠0) — the initial positions of the boxes.

The third line of each testcase contains m distinct integers in the increasing order b1,b2,…,bm (−109≤b1<b2<⋯<bm≤109; bi≠0) — the special positions.

The sum of n over all testcases doesn’t exceed 2⋅105. The sum of m over all testcases doesn’t exceed 2⋅105.

Output
For each testcase print a single integer — the maximum number of boxes that can be placed on special positions.


分析

正数部分和负数部分分开来考虑。
对于每一个特殊位置(该位置上没有箱子),我们都尝试将箱子正好推到这个位置,这样这个特殊点前面的所有箱子会从这个点向前延伸出去,然后看这部分延伸会碰到多少特殊位置即可,最后加上特殊点上本来就有箱子的个数(可用二分来找,具体看代码)。维护一个最大值。
负数部分和正数部分相加即是答案。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

#define N 200005
int n,m;
int input[N],a1[N],b1[N],a2[N],b2[N],cnt11,cnt12,cnt21,cnt22;
map<int,int> mp;

int solve(int a[],int b[],int lena,int lenb)
{
    
    
	int res = 0;
	mp.clear();
	int mh = 0;
	for(int i=1;i<=lena;i++) mp[a[i]] = 1;
	for(int i=1;i<=lenb;i++) if(mp[b[i]] == 1) mh++;
	
	res = mh;
	for(int i=1;i<=lenb;i++)
	{
    
    
		if(mp[b[i]] == 1)
		{
    
    
			mh--;
			continue;
		}
		int sum = upper_bound(a + 1, a + 1 + lena, b[i]) - a - 1;
		int pos = lower_bound(b + 1, b + 1 + lenb, b[i] - sum + 1) - b;
		res = max(res, mh + i - pos + 1);
	}
	return res;
}

int main()
{
    
    
	int Case = 1;
	scanf("%d",&Case);
	while(Case--)
	{
    
    
		cnt11 = cnt12 = cnt21 = cnt22 = 0;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
    
    
			scanf("%d",&input[i]);
			if(input[i] > 0) a1[++cnt11] = input[i];
		}
		for(int i=n;i>=1;i--)
		{
    
    
			if(input[i] < 0) a2[++cnt12] = -1 * input[i];
		}
		for(int i=1;i<=m;i++)
		{
    
    
			scanf("%d",&input[i]);
			if(input[i] > 0) b1[++cnt21] = input[i];
		}
		for(int i=m;i>=1;i--)
		{
    
    
			if(input[i] < 0) b2[++cnt22] = -1 * input[i];
		}
		int ans = 0;
		ans += solve(a1, b1, cnt11, cnt21);
		ans += solve(a2, b2, cnt12, cnt22);
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Sankkl1/article/details/114297869