码迷,mamicode.com
首页 > 其他好文 > 详细

CF33C Wonderful Randomized Sum 题解

时间:2020-03-22 15:36:24      阅读:83      评论:0      收藏:0      [点我收藏+]

标签:play   codeforce   复杂   不难   构造   span   spl   abs   坚强   

原题链接

简要题意:

你可以无限次的把该数组的一个前缀和后缀 \(\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)\).

CF33C Wonderful Randomized Sum 题解

标签:play   codeforce   复杂   不难   构造   span   spl   abs   坚强   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!