Educational CF Round 171

  1. 游记

理所当然VP
秒速过A,打B犯了一天的傻逼看错题
理所当然的只过了一道愉快开启改题生活
当然改题也挺那啥的

题解

A

挺简单的
X,Y的最小值,即找到长方形可框住的最大的正方形
直接输出此正方形的顶点坐标即可
证明考虑超出此正方形的点在旋转平移以后都会超出长方形范围
时间复杂度O(1)

B

如果是只能白点染成黑点,
那其实只能是A中元素两两一组且不重复出现
那其实要求的就是所有配对元素两两之间间隔最大值
考虑到如果出现不相邻的元素配对一定可以通过换成相邻元素配对来减小最大间隔
所以肯定是相邻配对
偶数的话就是(2k1,2k)这样,
否则会出现两个元素不满足最优决策落单,就会涂两个A以外的格子
奇数的话就是随便删一个元素,看看剩下n1个元素两两配对最大值
枚举每一个删掉的元素,再按照偶数情况解决,时间复杂度O(n2)
其实删一个元素,只有(i1,i+1)动了,其余的不动
可以直接维护前后缀两两配对后距离最大值,看看会发生什么变化
如果删一个奇数,配对情况还是前后缀和维护范围以内
如果删偶数,就需要用上下一个偶数的信息加上中间缝隙维护
时间复杂度O(n)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int o=222222;
int t,n,k,ans,a[o],f[o],s[o];
void in(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
}
void work(){
	if(n==1){
		ans=1;
		return;
	}
	if(n%2){
		ans=1e18;
		for(int i=2;i<=n;i+=2)
			f[i]=max(f[i-2],a[i]-a[i-1]);//前缀,偶数
		for(int i=n-1;i>=1;i-=2)
			s[i]=max(s[i+2],a[i+1]-a[i]);//后缀,偶数头上
		for(int i=1,now=0;i<=n;i++){
			now=0;
			if(i%2)now=max(f[i-1],s[i+1]);
			else{
			//	printf("i=%d,%d %d %d",i,a[i+1]-a[i-1],f[i-2],s[i+2]);
				now=max(now,a[i+1]-a[i-1]);
				now=max(now,f[i-2]);
				now=max(now,s[i+2]);
			}
			//printf("now=%d i=%d\n",now,i);
			ans=min(ans,now);
		}
	}
	else{
		for(int i=1;i<=n/2;i++)ans=max(a[2*i]-a[2*i-1],ans);
	}
}
void out(){
	cout<<ans<<endl;
}
void clear(){
	for(int i=1;i<=n;i++){
		f[i]=0,s[i]=0,a[i]=0;
	}
	n=ans=0;
}
#undef int 
int main(){
	cin>>t;
	while(t--){
		in();
		work();
		out();
		clear();
	}
	return 0;
}

提交记录

C

如果可以的话,能分开多买几次就不要集中买
否则可能会亏一次免费名额
其次,如果可以的话,用尽可能便宜的东西和贵的东西组一队拿下
倒序扫整个串,这样比较简单,出去肯定回不来了
对于si=0的情况,因为能多买就多买,买的那天的货物才会优惠,
所以i不可能会沾到优惠,直接加到答案里就行
否则,si=1的情况,既可能是直接免费拿下,也还可能是单着不急着配对
维护一个deque,把i扔到队头
如果碰上一个sj=0把队尾最大的那个i出去买下
(队列空那就是没办法了)
如果最后剩下,那就是队头配队尾
时间复杂度O(n)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int o=222222*2;
int T,n,ans,f[o];
char s[o];
deque<int>c;
int sum(int l,int r){
	return (l+r)*(r-l+1)/2;
}
void in(){
	cin>>n;
	scanf("%s",s+1);
}
void work(){
	for(int i=n;i>=1;i--){
		if(s[i]=='1')c.push_front(i);
		else{
			if(!c.empty())c.pop_back();
			ans+=i;
		}
	}
	while(!c.empty()){
		if(c.size()==1){
			ans+=c.front();
			break;
		}
		ans+=c.front();
		c.pop_front();
		c.pop_back();
	}
	
}
void out(){
	cout<<ans<<'\n';
}
void clear(){
	for(int i=1;i<=n;i++)s[i]=0;
	n=0,ans=0;
	c.clear();
}
#undef int 
int main(){
	cin>>T;
	while(T--){
		in();
		work();
		out();
		clear();
	}
	return 0;
}

提交记录

D

这个D就是无脑爆拆数学题了
首先前缀和惯例就是拆成(1,l1)(1,r)两部分做差
然后考虑(1,x)的部分
由于i=1xbi这个形式不太好做
我们倾向于拆成整的i=1aj=inS(i,j)和零的i=a+1cS(a+1,i)两部分
发现第一部分的第二层累加和第二部分累加相似,
所以用前缀和方式预处理第一部分的第一层累加,从而预处理第一部分
接下来考虑第二部分,还是前缀和化法
(对于这一部分,xy都是参数,视情况填入1n或其他)
i=xyS(x,i)=i=xysisx1=(i=xysi)(yx+1)sx1
再来个数组T维护s的前缀和,也就是TyTx1=(i=xysi)即可
剩下的就是填参数的事了
预处理两个前缀和时间复杂度O(n)
二分位置单次O(logn),计算第二部分答案单次O(1)
时间复杂度O(qlogn+n)

点击查看代码

E

按位拆开,如果ai的第j位为1就连一条ij+n的边
对于答案的形式,改成选的ai的个数加上所有的0位个数减去60
那其实求的就是ai的个数加所有0位的个数的最大值
这样的话所求的就是最大点独立集
而且图是二分图,
二分图最大点独立集等于顶点数减去最大匹配边数
最大匹配上Dinic干就完了

posted @   2K22  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示