codeforces1461E. Water Level

https://codeforces.com/contest/1461/problem/E

首先是y<=x的,也就是k总是在不断减少的时候,那么直接O(1)判断,看第t天减少的时候会不会<l就行

接下来是y>x的情况

如果(x+y)<=r-l+1,那么说明我k刚好<=x的时候直接+y就可以加,且不会加爆r,那么只要第一天可行直接就可以无限苟 (其实我当时没想清楚交了就过了,赛后雅米老师教我证的

否则的话,那么说明我每次只能在固定的位置t,t=[l,l+x-1]向上补1个y,也就是每次看k%x走重复了就成为一个环了,那么就可以无限苟,跑的过程重记录一下如果当前周期+y前连续减的时候到了第t填也直接yes

那么最多x个位置可以向上跳,最多只会循环x次,所以复杂度是O(x)的,也就是1e6

下面代码我用的(k-r)%x,其实也差不多,就是k%x,当时写的时候没想到判第一个结论。。。因为直接按我下面的代码写,模数重复的时候就可以无限苟,所以也包含了那种第一天可行就无限苟的情况

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

const int maxl=2e6+10;

int n,m,k,cnt,tot,cas,ans;
int a[maxl];
bool vis[maxl];
char s[maxl];

inline ll rd()
{
	ll x;cin>>x;
	return x;
}

inline void prework()
{
	__int128 k,l,r,t,x,y;
	k=rd();l=rd();r=rd();t=rd();x=rd();y=rd();
	if(k-t*x>=l){ans=1;return;}
	if(y>r-l){ans=0;return;}
	if(y<=x)
	{
		if(k+y<=r)
			k+=y;
		if(k-t*x+(t-1)*y>=l)
			ans=1;
		else
			ans=0;
		return;
	}
	__int128 sum=0;ans=1;
	while(1)
	{
		__int128 c=((k-r)%x+x)%x;
		if(vis[c])
			return;
		vis[c]=true;
		if(k-(t-sum)*x>=l)
			return;
		if(k+y<=r)
		{
			k+=y-x;
			continue;
		}
		__int128 tmp,d;
		tmp=k+y-r;
		d=tmp/x+(tmp%x!=0);
		if(k-d*x<l)
		{
			ans=0;
			return;
		}
		k-=d*x;sum+=d;
		k+=y;
	}
}

inline void mainwork()
{
	
}

inline void print()
{
	puts(ans?"Yes":"No");	
}

int main()
{
	int t=1;
	//scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/111056197