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没有被更新的情况。
标签:子串,Just,613,ll,Codeforces,字串,Max,include,sum 来源: https://blog.csdn.net/qq_44549690/article/details/103945402