CF33C Wonderful Randomized Sum 题解

原题链接

简要题意:

你可以无限次的把该数组的一个前缀和后缀 \(\times -1\),问最终的最大序列和。

这题盲目WA了数次才知道本质

这题89个数据吊打std

CF真好啊,发现一个错后面就不测了

下面,就以我艰辛的思维历程来构造本篇博客。

算法一

盲猜:所有数都可以变成正数。

然后绝对值相加。

连样例也没测。

然后,\(\frac{2}{89} pts\). 只过了前两个样例,第三个就死了。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

inline int read(){char ch=getchar();int f=1;while(ch<‘0‘ || ch>‘9‘) {if(ch==‘-‘) f=-f; ch=getchar();}
	int x=0;while(ch>=‘0‘ && ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x*f;}

int main(){
	int n=read(),s=0; while(n--) {
		int t=read();
		s+=abs(t);
	} printf("%d\n",s);
	return 0;
}

算法二

突然发现不符合样例!

仔细想了以下,嗯嗯,似乎只有开始的前一段负数和最后的后一段负数可以改变。

然后若有所思的写下一段代码。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

const int N=1e5+1;

inline int read(){char ch=getchar();int f=1;while(ch<‘0‘ || ch>‘9‘) {if(ch==‘-‘) f=-f; ch=getchar();}
	int x=0;while(ch>=‘0‘ && ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x*f;}

int n,a[N];
int s=0;

int main(){
	n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++)
		if(a[i]<0) a[i]=-a[i];
		else break; //前一段
	for(int i=n;i>=1;i--)
		if(a[i]<0) a[i]=-a[i];
		else break; //后一段
	for(int i=1;i<=n;i++) s+=a[i];
	printf("%d\n",s);
	return 0;
}

交上去,发现得了 \(\frac{6}{89}\) 分。

发现 \(a_i = 0\) 有点问题。

算法三

\(a_i = 0\)?然后加了几个等号。


#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

const int N=1e5+1;

inline int read(){char ch=getchar();int f=1;while(ch<‘0‘ || ch>‘9‘) {if(ch==‘-‘) f=-f; ch=getchar();}
	int x=0;while(ch>=‘0‘ && ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x*f;}

int n,a[N];
int s=0;

int main(){
	n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++)
		if(a[i]<=0) a[i]=-a[i];
		else break;
	for(int i=n;i>=1;i--)
		if(a[i]<=0) a[i]=-a[i];
		else break;
	for(int i=1;i<=n;i++) s+=a[i];
	printf("%d\n",s);
	return 0;
}

然后得了 \(\frac{8}{89}\) 分。

我却,我答案是负数,它答案是正数

算法四

真正感到自己 脑抽了 挺坚强的。

其实呢,我们还是要重视它,毕竟是 \(C\) 吗。(其实也不难)

你想,比方说前一段是 \(A\),后一段是 \(C\),重叠是 \(B\),一共是 \(S\).(\(\emptyset = 0\))

(指前缀、后缀、重叠部分、总部分的和)

此时答案为:

\[-(A+B)+C
\]

然而:

\[A+B+C=S
\]

(这是因为,中间一段经过两次之后没变,所以还是加上)

所以答案变形为:

\[-(A+B)+C = -(S-C)+C = 2 \times C - S
\]

显然让 \(C\) 越大越好。

那答案不就摆在面前了?

Dev-c++:那你还调试那么多次

因为,\(C\) 肯定是连续的一段并且你可以随便的取,所以:

\[\texttt{C = 原数列的最大子段和}
\]

哎呀,激动地写了个程序。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

const int N=1e5+1;

inline int read(){char ch=getchar();int f=1;while(ch<‘0‘ || ch>‘9‘) {if(ch==‘-‘) f=-f; ch=getchar();}
	int x=0;while(ch>=‘0‘ && ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x*f;}

int n,a[N];
int s=0,f[N];

int main(){
	n=read();
	for(int i=1;i<=n;i++) a[i]=read(),s+=a[i];
	int ans=a[1]; f[1]=a[1];
	for(int i=2;i<=n;i++) f[i]=max(f[i-1]+a[i],a[i]),ans=max(ans,f[i]);
	printf("%d\n",ans*2-s);
	return 0;
}

看上去没啥问题,然后得了 \(0pt\).

原因: \(\texttt{ans}\) 的初值应该是:

max(a[1],0)

导致第一个样例去世,然后全军覆没~

算法五

终于算是拨云见雾了,结果在临近 \(\texttt{AC}\) 的时候因为初值掉坑。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

const int N=1e5+1;

inline int read(){char ch=getchar();int f=1;while(ch<‘0‘ || ch>‘9‘) {if(ch==‘-‘) f=-f; ch=getchar();}
	int x=0;while(ch>=‘0‘ && ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x*f;}

int n,a[N];
int s=0,f[N];

int main(){
	n=read();
	for(int i=1;i<=n;i++) a[i]=read(),s+=a[i];
	int ans=max(a[1],0); f[1]=a[1];
	for(int i=2;i<=n;i++) f[i]=max(f[i-1]+a[i],a[i]),ans=max(ans,f[i]);
	printf("%d\n",ans*2-s);
	return 0;
}

终于 \(\text{AC}\) 了。时间复杂度:\(O(n)\).

原文地址:https://www.cnblogs.com/bifanwen/p/12546146.html

时间: 2024-10-03 11:00:41

CF33C Wonderful Randomized Sum 题解的相关文章

Codeforces-33C. Wonderful Randomized Sum

传送门 N个数,允许将前连续任意个数变化为其相反数,也允许把后连续任意个数变为相反数,求最大和 令dp[i][0]前i个数操作后能得到的最大值,dp[i][1]出去前i-1个数操作后能得到的最大值 注意初始化,不然对于答案为无需操作的情况会出错 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define INF 0x3f3f3f3f using n

LeetCode: Two Sum 题解

Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that

leetcode1 Two Sum题解

题目大概意思就是,我给你传进来一个vector容器和一个target,vector相当于一个数组,现在问target是有数组种哪两个数组成的,返回两个下标,注意函数的返回类型也是vector类型的,所以一定要注意. 题目刚到手的时候,发现这个与各大OJ套路不太一样啊,也就是与ACM不太一样,我还傻傻的调整输出格式什么的,而且这个是完善一个类的成员函数,而不是提交一个可以运行的完整代码,觉得还是挺新奇的. 思路分析 最开始的时候,以为这个如果数据量不是很大的时候可以桶排序暴力破解啊,我见建立了一个

01Two Sum题解

Tow Sum 原题概述: Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice. Example: Given nums =

Hdoj 1003.Max Sum 题解

Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14. Input The first line of the input contains

LeetCode 1 Two Sum 题解

Problem: Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please n

HDU1003 Max Sum 题解 动态规划 最大字段和扩展

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 题目大意: 求解一个序列的最大字段和,已经最前面的那个最大子段的起止坐标. 解题思路: 定义状态 \(f[i]\) 为以 \(a[i]\) 结尾的最大字段和,则有状态转移方程: \[f[i] = \max(0, f[i-1]) + a[i]\] 同时定义状态 \(s[i]\) 表示以 \(a[i]\) 结尾的最大字段的最左边元素的坐标,则有: 当 \(f[i] \lt 0\) 时,\(s[i]

HLJU14级贪心训练题解

由于有的题是很久之前写的题解(主要是我太懒了~~~),所以这里就不从新写了,直接给大家链接了^_^ A--最少拦截系统 题解链接:最少拦截系统 B--今年暑假不AC 题解链接:今年暑假不AC C--Tian Ji -- The Horse Racing 题解链接:Tian Ji -- The Horse Racing D--Max Sum 题解链接:Max Sum PS:有问题的,可以在群里讨论,或者是通过QQ问我,附上本弱QQ:1426137347   ^_^

[Leetcode] Sum 系列

Sum 系列题解 Two Sum题解 题目来源:https://leetcode.com/problems/two-sum/description/ Description Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one sol