agc022D - Shopping

题目大意

题解

很快想出来了,但细节挺多

可以发现答案是2L的倍数,每个数与T和X有关,和T的具体值关系不大

先把T模2L,将点分成四类,从右往左下车后能/否往右,从左往右下车后能/否往左,全否称为0,全是称为1,从右往左称为左,从左往右称为右

可以发现不存在先左后右的情况,因为一个左意味着x>L-x,右意味着x<L-x,矛盾

也就是没有在左右之间反复横跳的情况,只会在左/右和1之间横跳

于是扫过去判断,如果走了一个左/右最好能带走一个1,最后答案加上剩余1的个数再补成偶数

还要根据结尾讨论,如果结尾是0则一定要走到结尾再折返,否则可能可以通过1来折返

如果结尾是右的话可以通过右折返,并且这次折返带不走1(不然会错)

注意如果T是2L的倍数最好补成T=2L类别=0,不然还要讨论0和T的倍数情况

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

int a[300001],n,L,i,j,k,l,sum,Sum;
ll ans,X[300001],T[300001];

int main()
{
	#ifdef file
	freopen("agc022d.in","r",stdin);
	#endif
	
	scanf("%d%d",&n,&L);
	fo(i,1,n) scanf("%lld",&X[i]);
	fo(i,1,n)
	{
		scanf("%lld",&T[i]);
		if (!(T[i]%(L*2)))
		ans+=(T[i]/(L*2)-1)*2,T[i]=L*2;
		else
		ans+=(T[i]/(L*2))*2,T[i]%=L*2;
	}
	fo(i,1,n) a[i]=((X[i]*2)>=T[i])+2*(((L-X[i])*2)>=T[i]),ans+=(!a[i])*2;
	
	++ans,sum=0;
	if (a[n]==2)
	{
		fo(i,1,n)
		if (a[i]==3) ++sum,++Sum;
		else
		if (a[i]==2)
		{
			if (i==n) ++ans;
			else ans+=2;
			if (i<n && sum) --sum,--Sum;
		}
	}
	else
	{
		fo(i,1,n)
		if (a[i]==3) ++sum,++Sum;
		else
		if (a[i]==2)
		{
			ans+=2;
			if (sum) --sum,--Sum;
		}
		
		++ans;
		if (!a[n])
		{
			sum=0;
			fd(i,n,1)
			if (a[i]==3) ++sum;
			else
			if (a[i]==1)
			{
				ans+=2;
				if (sum) --sum,--Sum;
			}
		}
		else
		{
			sum=0;
			fd(i,n,1)
			if (a[i]==3)
			{
				if (i==n) --Sum;
				else ++sum;
			}
			else
			if (a[i]==1)
			{
				ans+=2;
				if (sum) --sum,--Sum;
			}
		}
	}
	ans+=Sum;
	
	ans+=ans&1;
	printf("%lld\n",ans*L);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2020-09-17 20:57  gmh77  阅读(327)  评论(0编辑  收藏  举报