EOJ 3294. WiFi

久违的eoj题解
思路来源

题面

单点时限: 3.0 sec
内存限制: 512 MB

章鱼王沿着国王大道巡视着他强大的王国,国王大道可以被看做一条直线,章鱼王的城堡的位置是 0 0 0

章鱼王知道他的国家里有 n n n 个 WiFi 信号发射器,第 i i i 个发射器在 a i a_i ai 位置,代表章鱼王城堡向东 a i a_i ai 米(若 a i < 0 a_i<0 ai<0 则为向西),WiFi 的强度为 b i b_i bi,代表 a i a_i ai 处能接收到强度为 b i b_i bi 的信号,而与信号发射器距离每增加 1 1 1 米,信号强度就减少 1 1 1,直到信号为 0 0 0 就不再减少。

章鱼王有 q q q 个询问,他想知道在国王大道 c i c_i ci 位置处能接收到的最大信号强度。

输入格式
第一行为数据组数 T ( T ≤ 10 ) T(T\leq 10) T(T10)

每组数据第一行为 n , q n,q n,q ,第二行为 n n n 个数字 a i a_i ai,第三行为 n n n 个数字 b i b_i bi,接下来一行 q q q 个询问 c i c_i ci

保证 40 % 40\% 40% 的数据满足: 1 ≤ n , q ≤ 1000 1\leq n,q\leq 1000 1n,q1000
保证 100 % 100\% 100% 的数据满足: 1 ≤ n , q ≤ 1 0 5 , 0 ≤ ∣ a i ∣ ≤ 1 0 9 , 0 ≤ b i ≤ 1 0 9 , 0 ≤ ∣ c i ∣ ≤ 1 0 9 1\leq n,q\leq 10^5, 0\leq |a_i|\leq 10^9,0\leq b_i\leq 10^9,0\leq |c_i|\leq 10^9 1n,q105,0ai109,0bi109,0ci109

所有数均为整数。

输出格式
对于每组数据中的每个询问,输出一行结果。

样例

input
1
2 3
0 6
3 6
0 -1 5
output
3
2
5

思路分析

假设在位置 p o s pos pos 处的WiFi发射器的信号强度为 v a l val val,该WiFi发射器在点 x x x 处的信号强度为 p p p 。 则可得 p = v a l − ∣ x − p o s ∣ = { v a l + p o s − x ( x 左 边 ) v a l − p o s + x ( x 右 边 ) p = val-|x-pos|=\left\{\begin{matrix}val+pos-x (x左边) \\ val-pos+x(x右边)\end{matrix}\right. p=valxpos={ val+posxxvalpos+xx
要求得 p p p 的最大值,即找到 x x x 左边 v a l + p o s val+pos val+pos 的最大值和 x x x 右边 v a l − p o s val-pos valpos 的最大值。由于数据规模大,用顺序查找暴搜必然超时,所以采用二分查找。

对于 x x x左边的WiFi发射器,有 x − p o s ≥ 0 x-pos \geq 0 xpos0 p = v a l − x + p o s p = val - x + pos p=valx+pos ,那么我们只需二分查找找到 x ≥ p o s x \geq pos xpos的点在按 ( v a l + p o s ) (val+pos) (val+pos)键值排序的最后一个符合 x ≥ p o s x \geq pos xpos的Wifi发射器
同理,对于 x x x右边, x − p o s < 0 x-pos < 0 xpos<0 p = v a l + x − p o s p = val + x - pos p=val+xpos,二分查找找到 x < p o s x < pos x<pos的点在按 ( v a l − p o s ) (val-pos) (valpos)键值排序的最后一个符合 x < p o s x < pos x<pos 的Wifi发射器

但是当我们按照 v a l − p o s val-pos valpos 或者 v a l + p o s val + pos val+pos 排序之后, p o s pos pos本身在数组中不一定是单调的。我们知道二分的前提是单调性。于是利用单调队列,在不影响原数组的顺序的情况下,处理出 p o s pos pos的单调性。

ac代码

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

struct node
{
    
    
	int pos,val;
};

bool cmp(node a,node b)
{
    
    
	if(a.pos + a.val != b.pos + b.val)
		return a.pos + a.val < b.pos + b.val;
	return a.pos > b.pos; 
}

bool cmp1(node a,node b)
{
    
    
	if (a.val - a.pos != b.val - b.pos)
		return a.val - a.pos < b.val - b.pos;
	return a.pos < b.pos;
}

int n,q;

int main()
{
    
    
	int T;
	cin >> T;
	while(T--)
	{
    
    
		cin >> n >> q;
		node info[n], info1[n];
		for(int i=0;i<n;i++)
		{
    
    
			cin >> info[i].pos;
			info1[i].pos=info[i].pos;
		}
		for(int i=0;i<n;i++)
		{
    
    
			cin >> info[i].val;
			info1[i].val=info[i].val;
		}
		//按照x左右不同键值排序
		sort(info,info+n,cmp);
		sort(info1,info1+n,cmp1);
		
		//单调队列,left中的pos递增,right中pos递减。两个队列中键值都是递增
		vector<node> left,right;
		left.push_back(info[0]);
		right.push_back(info1[0]);
		for(int i=1;i<n;i++)
		{
    
    
			int rear=left.size()-1;
			if(info[i].pos > left[rear].pos)
			{
    
    
				left.push_back(info[i]);
				continue;
			}
			else if(info[i].pos < left[rear].pos)
			{
    
    
				//pos更小更易满足条件 x >= my[i].pos,且由于已经排序了p1会更大
				while(left.size()&&info[i].pos<left[left.size()-1].pos)
					left.pop_back();
				left.push_back(info[i]);
			}
		}
		
		for(int i=1;i<n;i++)
		{
    
    
			int rear=right.size()-1;
			if(info1[i].pos < right[rear].pos)
			{
    
    
				right.push_back(info1[i]);
				continue;
			}
			else if(info1[i].pos > right[rear].pos)
			{
    
    
				//pos更大更易满足条件 x < my[i].pos,且由于已经排序了p2会更大
				while(right.size()&&info1[i].pos>right[right.size()-1].pos)
					right.pop_back();
				right.push_back(info1[i]);
			}
		}
		
		int c;
		while(q--) 
		{
    
    
			cin >> c;
			int p1=0,p2=0;
			
			//二分查找
			int l,r;
			l=0,r=left.size()-1;
			while(l < r)
			{
    
    
				int mid = (l+r+1)>>1;
				if(left[mid].pos<=c)
					l=mid;
				else
					r=mid-1;
			}
			if(left[l].pos<=c)
				p1=max(0,left[l].pos+left[l].val-c);
				
			l=0,r=right.size()-1;
			while(l < r)
			{
    
    
				int mid = (l+r+1)>>1;
				if(right[mid].pos>c)
					l=mid;
				else
					r=mid-1;
			}
			if(right[l].pos>c)
				p2=max(0,right[l].val-right[l].pos+c);
				
			cout << max(p1,p2) << endl;
		} 
	}
}

猜你喜欢

转载自blog.csdn.net/qq_45401156/article/details/113742682
今日推荐