题目
给你一个序列A
请你判断是否有一个子区间使得大于等于整个区间的总和。
如果有返回NO
否则YES
题解思路
根据之前任意区间的思想,我们可以先处理出前缀和,然后排序,二分判断两个区间差是否大于等于区间总和SP即可。
定住一边为s[i] +sp 然后利用lower_bound()判断之后的区间s[k]是否存在大于等于它的。
这里需要特判两个都是端点的情况(即s[i]为0,s[k]为sp),当前缀和中不存在等于0和s[k]的数的时候这些判定出答案就是非法的,因为这样就是取整个区间了。
这里用lower_bound()犯了个大病,减去去了begin的下标,因为都是从数组取出,减去s这个数组的指针就行了的。
贪心做法
当某段前缀区间小于等于0的时候,删除这段区间必然可以使答案变大。
当大于等于sum的时候就必然存在一个区间了。
最大区间做法
求出区间中最大的一段子区间来与sum比较
每次求前缀的时候保证一个当前位置的最大区间值,和最小区间值,
每次用求出的前缀减去最小值或者不减,看看能不能更新出一个更大的值。
AC代码
任意区间
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 100010 ;
int a[N] ;
long long sum[N] ;
bool cmp (int x ,int y )
{
return x > y ;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T ;
cin >> T ;
while (T--)
{
sum[0] = 0 ;
int n ,book1 = 0 , book2 = 0 ;
long long sp ;
cin >> n ;
for ( int i = 1 ; i <= n ; i++ )
{
cin >> a[i] ;
sum[i] = sum[i-1] + a[i] ;
if( i == n )
sp = sum[i] ;
}
for ( int i = 1 ; i < n ; i++ )
{
if (sum[i] == 0 )
{
book1 = 1 ;
}
if (sum[i] == sum[n] )
{
book2 = 1 ;
}
}
sort(sum,sum+n+1) ;
int falg = 0 ;
/*
for (int i = 0 ; i <= n ; i++ )
cout << sum[i] << " ";
cout << "\n" ;
cout << sp << "\n" ;
*/
for (int i = 0 ; i <= n ; i++ )
{
int k = lower_bound(sum+1+i,sum+1+n,sum[i]+sp) - sum ;
if (k > i && k <= n )
{
if (sum[i] == 0 && sum[k] == sp && !book1 && !book2 )
{
if ( n == k )
continue ;
}
//cout << sum[i] + sp << "\n" ;
//cout << k << "\n" ;
//cout << sum[k] << "\n" ;
falg = 1 ;
break ;
}
}
if (falg)
cout << "NO\n" ;
else
cout << "YES\n" ;
}
return 0 ;
}
贪心
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 100010 ;
int a[N] ;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T ;
cin >> T ;
while (T--)
{
int n ;
cin >> n ;
long long sum = 0 ;
for (int i = 1 ; i <= n ; i++ )
{
cin>>a[i] ;
sum += a[i] ;
}
int falg = 0 ;
long long p1 = 0 ;
for (int i = 1 ; i < n ; i++ )
{
p1 += a[i] ;
if (p1 <= 0 || p1 >= sum )
{
falg = 1;
}
}
if (falg)
cout << "NO\n" ;
else
cout << "YES\n" ;
}
return 0 ;
}
最大区间做法
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 100010 ;
long long a[N] ;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T ;
cin >> T ;
while (T--)
{
int n ;
cin >> n ;
long long sum = 0 ;
long long ma = -INF , mi = INF;
for (int i = 1 ; i <= n ; i++ )
{
cin>>a[i] ;
a[i] = a[i] + a[i-1] ;
ma = max(a[i]-mi , ma ) ;
mi = min( mi , a[i] ) ;
}
int falg = 0 ;
for (int i = 1 ; i < n ; i++ )
{
ma = max( ma , a[i] ) ;
}
if ( ma >= a[n] )
cout << "NO\n" ;
else
cout << "YES\n" ;
}
return 0 ;
}