P10217 [省選聯考 2024] 季風

liuboom發表於2024-12-06

P10217 [省選聯考 2024] 季風

[省選聯考 2024] 季風

題目背景

生活在二維平面的小 X 準備拜訪小 Y,但由於氣候的變化,平面上颳起了季風。小 X 想知道季風的影響下,TA 至少要多少天能夠到達小 Y 的家,但小 X 也是第一次遇見這種怪事,所以請精通演算法的你來幫忙。

題目描述

給定 \(n,k,x,y\)\(2n\) 個整數 \(x_0,y_0,x_1,y_1,\dots,x_{n-1},y_{n-1}\)

找到最小的非負整數 \(m\),使得存在 \(2m\) 個實數 \(x_0',y_0',x_1',y_1',\dots,x_{m-1}',y_{m-1}'\) 滿足以下條件,或報告不存在這樣的 \(m\)

  • \(\sum \limits_{i=0}^{m-1} (x_i'+x_{i \bmod n})=x\)
  • \(\sum \limits_{i=0}^{m-1} (y_i'+y_{i \bmod n})=y\)
  • \(\forall 0\leq i\leq m-1,|x_i'|+|y_i'|\leq k\)

特別地,\(m=0\) 時,認為 \(\sum \limits_{i=0}^{m-1} (x_i'+x_{i \bmod n})\)\(\sum \limits_{i=0}^{m-1} (y_i'+y_{i \bmod n})\) 均為 \(0\)

輸入格式

本題有多組測試資料。輸入的第一行一個整數 \(T\) 表示測試資料組數。

對於每組測試資料,

  • 第一行四個整數 \(n,k,x,y\)
  • 接下來 \(n\) 行,第 \(i\) 行兩個整數 \(x_{i-1},y_{i-1}\)

輸出格式

對於每組測試資料輸出一行一個整數,如果存在滿足題意的 \(m\),輸出其最小可能值,否則輸出 \(-1\)

歡樂補題捏

首先我們來整理一下式子:
我們將n無限迴圈,則原式可化為:
$ mx_i'$ =\(x\) - \(\sum \limits_{i=0}^{m-1} x_i\)

$ my_i'$ =\(y\) - \(\sum \limits_{i=0}^{m-1} y_i\)

|\(x\) -
\(\sum \limits_{i=0}^{m-1} x_i\)| +
|\(y\) -
\(\sum \limits_{i=0}^{m-1} y_i\)| \(<=\) \(mk\)

把絕對值拆了之後:

\(\sum \limits_{i=0}^{m-1} (x_i+y_i+k)\) >=\(X+Y\)

\(\sum \limits_{i=0}^{m-1} (x_i-y_i+k)\) >=\(X-Y\)

\(\sum \limits_{i=0}^{m-1} (-x_i+y_i+k)\) >=\(-X+Y\)

\(\sum \limits_{i=0}^{m-1} (-x_i-y_i+k)\) >=\(-X-Y\)

求出同時滿足這四個條件的m

\(s_x\)=\(\sum \limits_{i=1}^{x} (x_i+y_i+k)\)
\(sum=s_n\)

考慮列舉每個1<=i<=n:
\(l_i\)為最後一位取在\(i\)時m的下界,\(r_i\)為上界
\((l_i /r_i=X+Y-S_i)/sum\)
\(l_i/r_i\)取決於分母的符號

特殊的,當sum=時,若\(S_i>=X+Y\)則任取,否則不能

同理,對上面提到過的四種情況做相同的討論,得出\(l,r\)

最後統計答案時,若滿足\(l_i<=r_i\)
\(ans=min(ans,l_i*n+i)\)

然後這題就做完了

Code

#include<bits/stdc++.h>
#define int long long
const int N=1e6+5;
const int inf=1e18;
using namespace std;
int x[N],y[N],s[N],l[N],r[N];
int n,k,X,Y;
void calc(int fx,int fy)
{
	int pos=fx*X+fy*Y;
	for(int i=1;i<=n;i++)
	{
		s[i]=s[i-1]+x[i]*fx+y[i]*fy+k;
	}
	if(!s[n])
	{
		for(int i=1;i<=n;i++)
		{
			if(s[i]<pos)r[i]=-1;
		}
		return ;
	}
	else
	{
		for(int i=1,fz,fm=s[n];i<=n;i++)
		{
			fz=pos-s[i];
			if(s[n]>0)
			{
				if(fz>0)//ans_l=(pos-s[i])/s[n] (bigger)
				{
					l[i]=max(l[i],(fz%fm? fz/fm+1 : fz/fm));
				}
			}
			else //ans_r=(pos-s[i])/s[n] (lower)
			{
				if(fz>0)//ans_r<0
				{
					r[i]=-1ll;
				}
				else
				{
					r[i]=min(r[i],fz/fm);
				}
			}
		}
	}
}
void work()
{
	cin>>n>>k>>X>>Y;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&x[i],&y[i]);
		l[i]=0;
		r[i]=inf;
	}
	if(!X&&!Y)
	{
		printf("%lld\n", 0ll);
		return;
	}
	int ans=inf;
	calc(1,1);calc(1,-1);calc(-1,1);calc(-1,-1);
	for(int i=1;i<=n;i++)
	{
		if(l[i]<=r[i])
		ans=min(ans,l[i]*n+i);
	}
	printf("%lld\n",ans==inf? -1ll : ans);
}
#undef int 
int main()
{
	//freopen("P10217_1.in","r",stdin);//freopen("P10217.out","w",stdout);
	int T;
	cin>>T;
	while(T--)
	{
		work();
	}
}

相關文章