Codeforces Round #613 (Div. 2)——B. Just Eat It!(最大子串)

题目大意:

题目传送门:https://codeforces.com/contest/1285/problem/B
给你一串数字,有正有负,问所有数字的和是不是严格大于任何一个子段(不包括全段)的和。

题目分析:

本题思路很简单,就是寻找最大子串的值与全串的值相比较,如果全串大于最大字串,则输出“YES”,否则输出“NO”。
寻找最大字串的思路是:先记录整个串开始的位置,然后用一个值sum来表示从开始位置到当前位置的所有数字的和,如果这个和大于Max,就更新Max。如果这个支小于0,则重新开始寻找开始位置并还原sum。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string> 
#include<vector>
#include<stack>
#include<queue> 
#define PI 3.1415926
typedef long long ll;
using namespace std;
ll Max = -(1<<30);//初始化Max为一个很小的数,因为前面有负号 
ll startIndex = 0;
ll endIndex = 0;
void findMax(ll arr[], ll len){
    ll i,sum = 0;
    ll tempStartIndex = 0;
    for(i = 0; i < len; i++){
      
        if(sum == 0){
            tempStartIndex = i;  //示新的子串,记录临时开始位置
        }
        sum += arr[i];
        if(sum > Max){ //新的字串的和比原来的大
            Max = sum;
            startIndex = tempStartIndex; //记录新的字串的开始位置
            endIndex = i; //记录结束位置
        }
        if(sum < 0){
            sum = 0; //还原,开始新的子串
        }
    }
}
int main()
{
	ll t=0;
	cin>>t;
	static ll a[100010]={0};
	while(t--)
	{
		ll n=0,d=1,flag=0,Y=0,A=0;
		scanf("%lld",&n);
		for(ll i=0;i<n;i++)
		{
			scanf("%lld",&a[i]);
			Y+=a[i];
		}
		findMax(a,n);	
		if(Y>Max)//全串的值大于最大子串
		cout<<"YES"<<endl;
		else if(Y==Max&&startIndex==0&&endIndex==n-1)//最大子串就是全串
		cout<<"YES"<<endl;
		else 
		cout<<"NO"<<endl;
		//忘记初始化了
		 Max = -(1<<30);
		 startIndex = 0;
		 endIndex = 0;
	}
	return 0;
}

注意事项:

因为我的Max,startIndex,endIndex定义的是全局变量,所以每一次查询之后都要初始化,之前因为这个问题wa了5发,一定要注意细节!!!
还有,初始化关于Max = -(1<<30)的解释如下:
<<表示将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
例:a = a << 2 将a的二进制位左移2位,右补0,
左移1位后a = a * 2;
若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
1<<30 表示1左移30位,每左移一位乘以2,所以就是1*2^30=1073741824。
前面加上负号就是初始化Max为一个很小的值,保证不会出现Max没有被更新的情况。

发布了22 篇原创文章 · 获赞 2 · 访问量 576

猜你喜欢

转载自blog.csdn.net/qq_44549690/article/details/103945402