Codeforces Round 885 (Div. 2)A-C题解

本文详细介绍了Codeforces编程竞赛中三道题目(A-C题)的解决方案,涉及二维坐标分析、数组处理和颜色路径规划等算法思想。题目包括判断李华能否避免被朋友找到、改变木板颜色规划路径以及数组操作达到特定状态的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Codeforces Round 885 (Div. 2)A-C题解

链接

A

题意:给你一个长度为n*m的商场,每一个商场都有它自己的坐标(x,y),1<=x<=n,1<=y<=m,
然后给你李华和她的几个朋友的坐标,在每一分钟后李华会去她相邻的商场,之后她的朋友也会去她相邻的商场(在已知李华去哪个商场之后),此时1分钟结束。现在李华的朋友要去寻找李华,李华很着急,问你现在她是否可以一直不被她的朋友找到(即在某一分钟后李华的坐标和她的其中一个朋友的坐标相同)。

思路:

首先,显而易见的,如果李华在角落,并且有个人(李华&friend)的坐标满足
|x李华-x李华&friend|+|y李华-y李华&friend|=1
那么李华接下来无论怎么走,李华friend都是可以直接抓到她的。

李华在角落,可以看做是在一条y=kx+b的一条直线上(k=1或者k=-1,其实都一样,就默认k为1)。李华的移动可以看做是这条直线k不变,b在不断变化。
那么李华friend也是在这一条直线上。那么我们可以发现,对于这两个人,无论李华怎么走,李华friend都是可以和李华保持都是在同一条直线上,并且在此基础之上李华friend会不断接近李华,直到把李华逼近到角落,此时李华一定会被抓住。

那么说了这么多,可以得到一条结论,对于李华所在的y=x+b这条直线上,如果有李华friend也在李华所在的这一条直线上,那么李华一定会被抓住。

那如果李华和李华friend不在同一条直线上呢

对于这种情况,我们假设某一个李华friend在直线y=x+b1,而李华在直线y=x+b2,首先李华向周围移动一格,那么k不变,b2也会+1或者-1。那对于李华friend,k也不发生变化,b1同样+1或者-1
1.如果b2+1并且b1+1或者b2-1并且b1-1,b1和b2的差不发生变化,两直线不会相同;
2.如果b1+1&&b2-1 或者 b1-1&&b2+1 ,那么b1和b2的差值会增加2或者减少2,那么如果当 abs(b1-b2)%2==0 的时候,无论李华怎么走,李华friend也可以在某一时刻走到与李华相同直线的时候。

那么对于李华和她的所有朋友,如果两者直线的b相差的绝对值%2==0,那么这个人一定

可以抓住李华,否则就一定抓不住。

代码:

void slove( )
{
   int t,xx,yy;
   cin>>n>>m>>t;
   cin>>xx>>yy;
   for(int i =1;i<=t;i++)
   {
   	cin>>x[i]>>y[i];
   }

   	for(int i =1;i<=t;i++)
   	{
   		if(abs(abs(yy-xx)-abs(y[i]-x[i]))%2==0){
   			cout<<"NO\n";
   			return ;
   		}
   	}
   	cout<<"YES\n";
   	return ;

}

B

题意:有一条由n个木板组成的桥,每个目板都有自己的颜色,现在李华在第一块木板面前,她想只走一种颜色的木板,现在问你,在可以改变一块(或者0块)木板的颜色的情况下,李华只走一种颜色的木板,李华一次需要跨过的木板的最大值的最小是多少。

思路:

更新每种颜色的木板出现的下标,然后纪录最大的次大的同种颜色的木板到上一个木板的距离。最后用n+1代表最后一块木板更新一遍。
之后对每个元素的最大值进行改变颜色的操作,max=max/2,和次大值取最大值。然后取每种颜色的最小值即可。

代码:

void slove( )
{
   int t;
   cin>>n>>m;
   map<int,int>p;           // 存当前元素的前一个出现的元素的下标
   map<int,pair<int,int>>q; // 存当前元素的距离的最大值和次大值
   for(int i =1;i<=n;i++) {
   	cin>>s[i];
   	if(!q[s[i]].first) q[s[i]].first=i-p[s[i]];//没有最大值
   	else {
   		int dis=i-p[s[i]];//当前元素与上一个元素的下标的差
   		if(!q[s[i]].second) {//没有次大值
   			q[s[i]].second=dis;
   			if(q[s[i]].second>q[s[i]].first)swap(q[s[i]].first,q[s[i]].second);//	转换最大值与次大值
   		}
   		else {//次大值和最大值都存在
   			if(dis>q[s[i]].first){//当前距离大于最大值,直接覆盖
   				q[s[i]].second=q[s[i]].first;
   				q[s[i]].first=dis;
   			}
   			else if(dis>q[s[i]].second)//如果只大于次大值
   			q[s[i]].second=dis;
   		}
   	}
   	p[s[i]]=i;//更新距离
   }

   for(auto i:p)//所有存在的颜色更新距离
   {
   	int j=i.first,x=i.second;
   //	cout<<j<<" "<<q[j].first<<" "<<q[j].second<<endl;		
   	if(!q[j].second)
   	{
   		q[j].second=n+1-x;
   		if(q[j].second>q[j].first)swap(q[j].first,q[j].second);			
   	}
   	else{
   		int dis=n+1-x;
   		//cout<<dis<<endl;

   			if(dis>q[j].first){
   				q[j].second=q[j].first;
   				q[j].first=dis;
   			}
   			else if(dis>q[j].second)
   			q[j].second=dis;			
   		//cout<<j<<" "<<q[j].first<<" "<<q[j].second<<endl;
   	}

   }

   int res=n/2;
   for(auto i:q)
   {
   	int j=i.first,ma=i.second.first-1,mi=i.second.second-1;
   	//cout<<j<<" "<<ma<<" "<<mi<<endl;
   	res=min(res,max(ma/2,mi));
   }
   cout<<res<<endl;

C

题意:给你a,b两个数组,让你不断进行以下操作:
新建一个数组c,使ci=|ai-bi|,ai=bi,bi=ci.
问经过任意次后是否可以使 a 数组中的每个数全为0。

思路:

首先每组的ai,bi是独立的,那么我们可以考虑每组的(a,b)变成(0,x)的情况。
通过规律我们可以看出当已经是(0,x)这种情况下,之后的变化是
( 0 , x ) - > ( x , x ) - > ( x , 0 ) - > ( 0 , x ),那么就是每三次操作为一次循环,
I那么对于每组所需要的操作sI,只需要判断他们取模三是否一致即可。

有一种可以简化时间的方法:
当x>=2y时.他会进行三次操作
( x , y ) - > ( y , x - y ) - > ( x - y , x - 2y ) - > ( x - 2y , y ) ;那么我们可以使x对2y取余,这样不影响最后的答案,之后可以直接暴力算次数即可。

代码:

void slove( )
{
   b[0]=b[1]=b[2]=0;
   int t;
   sc_int(n);

   for(int i =1;i<=n;i++)cin>>a[i];

   for(int i =1;i<=n;i++)
   {
   
   	int x;
   	cin>>x;
   	if(x==0&&a[i]==0)continue;
   	if(x) a[i]%=2*x;

   	int time=0,k;
   	while(a[i])	
   	{
   		k=abs(a[i]-x);
   		x=a[i];
   		a[i]=k;
   		if(x)a[i]%=2*x;
   		time++;
   	}
   	b[time%3]++;		
   }
   int res=0;
   if(b[0])res++;
   if(b[1])res++;
   if(b[2])res++;
   if(res<=1)cout<<"YES\n";
   else cout<<"NO\n";


   
//	cout<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值