记录一道知乎上看到的POI

前言:毕竟是信息竞赛的题,题的难度系数极大。

题目描述

有一个长度为n的实数数组a,可以进行任意轮的操作,每轮选择一个i(0 < i < n-1)操作为a[i] = a[i+1] + a[i-1] - a[i],问最终a[0]+a[1]+…+a[n-1]最大可以是多少?

题目求解

创建一个a的差分数据b,有b[i] = a[i] - a[i-1]。则对a数组的操作相当于b数组的交换b[i]和b[i+1],当b[i+1]大于b[i]时,交换b[i]和b[i+1]相当于a[i]变大;当b[i+1]小于b[i]时,交换b[i]和b[i+1]相当于a[i]变小。故想让a数组和最大,即对b数组降序排序,还原得到a就可得到结果。

详细说明

  1. 开始b[i] = a[i] - a[i-1],b[i+1] = a[i+1] - a[i]。a数组进行一轮操作后,a[i-1],a[i],a[i+1]变为了a[i-1],a[i+1] + a[i-1] - a[i],a[i+1]。此时,b[i] = a[i+1] + a[i-1] - a[i] - a[i-1] = a[i+1] - a[i],b[i+1] = a[i+1] - (a[i+1] + a[i-1] - a[i]) = a[i] - a[i-1]相当于之前的b[i]和b[i+1]交换了位置。
  2. 而若b[i+1] > b[i],则有a[i+1] - a[i] > a[i] - a[i-1],相当于a[i+1] + a[i-1] - a[i] > a[i],即表示进行一轮操作后a[i]的值变大,即表示此时需要交换b[i]和b[i+1]。

参考代码

仅供参考

#include<stdio.h>
#include<stdlib.h>
//c语言调用快排,需要传的参数 ,表示想要升序还是降序
int cmp(const void *a, const void *b)
{
    return *(int *)b - *(int *)a; //由大到小排序
}
#define len 10
int main(){
	int a[len] = {23,12,5,23,45,18,9,81,29,53};
	int b[len];
	//得到a的差分数组b
	b[0] = a[0];
	for(int i = 1; i < len; ++i){
		b[i] = a[i] - a[i-1];
	} 
	qsort(b, 10, sizeof(int), cmp);//对差分数组降序排序 
	//还原数组a
	for(int i = 1; i < len; ++i){
		a[i] = b[i] + a[i-1];
	}
	//输出结果
	int sum = 0;
	for(int i = 0; i < len; ++i){
		sum += a[i];
	}
	printf("%d",sum);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值