CF 718 E - Group Photo

这篇博客探讨了一种解决AI数组排列问题的方法,其中C序列要求递增且相隔两个数的差值递增,P序列要求递减。通过枚举和二分搜索策略,确定满足条件的C和P序列组合。文章详细分析了五种特殊情况,并提供了相应的解决方案,最终给出了完整的C++代码实现。

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

给出一个ai数组,然后构造C和P序列,两个序列的合集是1到n的排列。然后c的排列对应的a的和要小于p对应的a的和。

而且C序列相隔两个数的差值要递增,P要递减。 具体还是去看题目吧(少写点字)

 

由于C要递增,P要递减,因此只有几种情况

1.C一开始是连续的,然后后面是差值为2。 (12345 7 9 11 。。。。)

2.C前面放一个P,然后从2开始的第一种情况

3.整个CP序列最后是C,然后前面按第一种情况

4.2,3整合

还有特殊的两种

5. CP序列C都在最后面。

6. 没有C

 

 

对于前4种,枚举c连续到那个位置,然后二分后面差值为2的下标最远可以去到哪里,然后就加加减减判断下前面有没有多的p后面有没有多的c就好了。

由于枚举的时候,2,3会和第一种有重复 (CPC结尾),因此2,3在做二分的时候,最右只能去到n-3(n-2就会出现重复了). (就是这里写错了导致没A到啊。。上分失败T_T)

对于第5种,就直接枚举后面有多少个C了

第6种直接加1就好了。

 

 

using namespace std;
int mod = 998244353;
//int mod = 1e9+7;

int n,m;

ll sum[N],qs[N];
ll a[N];


int sol(int idx, int n, ll tot, ll es, ll ecs){
	ll cur_sum = sum[idx]-es + ecs;
	int l = idx, r = n+1;
	while(l+4<r){
		int mid = (l+r)>>1;
		int p_mid = mid;
		if((mid - idx)%2){
			p_mid--;
		}
		ll s = qs[p_mid] - qs[idx];
		s += cur_sum;
		ll ss = tot - s;
		if(s<ss){
			l = p_mid;
		}
		else {
			r = p_mid;
		}
	}
	int ret = l-1;
	for(int i = l; i <=min(n,r); i+=2){
		ll s = qs[i] - qs[idx];
		s += cur_sum;
		ll ss = tot - s;
		if(s<ss){
			ret = i;
		}
	}
	if(ret<l){
		return 0;
	}
	return (ret + 2 - idx)/2;
}

int main(){

	int t;
	cin>>t;
	while(t--){
		sf("%d",&n);
		fr(i,1,n+1){
			sf("%lld",&a[i]);
			sum[i] = sum[i-1]+a[i];
		}
		fr(i,1,n+1){
			if(i==1) qs[i] = a[i];
			else qs[i] = qs[i-2] + a[i];
		}
		ll ans = 0;
		for(int i = 1; i <=n; ++i){
			ans = (ans + sol(i,n,sum[n],0,0))%mod;
			if(i>1){
				ans = (ans + sol(i,n,sum[n],sum[1],0))%mod;
			}
			if(i<n){
				ans = (ans + sol(i,n-3,sum[n],0,a[n]))%mod;
			}
			if(i>1&&i<n){
				ans = (ans + sol(i,n-3,sum[n],a[1],a[n]))%mod;
			}
		}
		for(int i = 3; i <=n; ++i){
			ll s1 = sum[i-1];
			ll s2 = sum[n]- s1;
			if(s2<s1){
				ans = (ans + 1 ) %mod;
			}
		}
		cout<<ans+1<<endl;
	}
}


 

《C++编程实例100篇》是一本深入实践、极具价值的编程教程,它针对C++编程语言提供了丰富的实例,旨在帮助读者更好地理解和掌握C++的各项特性与编程技巧。这本书的经典之处在于它将理论与实践相结合,通过100个精心设计的编程实例,覆盖了C++的各个核心领域,包括基础语法、面向对象编程、模板、异常处理、STL(标准模板库)等。 我们来探讨C++的基础语法。C++是C语言的增强版,它保留了C语言的高效性和灵活性,并引入了类、对象和继承等面向对象编程概念。基础语法包括变量声明、数据类型、运算符、控制结构(如if语句、for循环、while循环)、函数的定义和调用等。在实例中,你可能会遇到如何编写简单的程序,如计算两个数的和,或者实现一个简单的猜数字游戏。 C++的面向对象编程是其一大特色。通过类和对象,你可以构建复杂的软件系统。类是对象的蓝图,它定义了对象的属性和行为。实例化一个类,就是创建一个具体的对象。继承允许你创建新的类,这些类从现有的类派生,共享其属性和方法,同时可以添加新的功能。多态性是面向对象的另一个关键特性,它使得不同类型的对象可以对同一消息作出不同的响应。这些概念在实例中会以各种形式展现,例如设计一个图形界面的类层次,或实现一个简单的模拟游戏。 接下来是模板,C++的模板功能让代码更加通用,可以处理不同类型的数据。模板分为函数模板和类模板,前者可以创建泛型函数,后者可以创建泛型类。通过模板,你可以编写出高效且灵活的代码,比如实现一个通用的排序算法。 异常处理是C++中用于处理程序运行时错误的机制。当程序出现异常情况时,可以抛出一个异常,然后在适当的点捕获并处理这个异常。这使得代码能够优雅地处理错误,而不是让程序崩溃。实例中可能会有涉及文件操作或网络通信时可能出现的异常处理示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值