子序列

给定一个序列a[i],取出一段连续的子序列,使得子序列的和的绝对值最小。

N<=10^6,a[i]<=10^9。

sol:先求出前缀和,我们考虑到,任何一个子序列和的绝对值,都可以表示为|s[x]-s[y]|(x大于y),那么任何有一个|s[x]-s[y]|(x大于y),都对应一个子序列和的绝对值。所以,我们只要找出一组(x,y),使得|s[x]-s[y]|最小即可。故,可对前缀和排序后,依次比较|s[i]-s[i+1]的绝对值,从中选择最小的。

如a[i]:2 8 -20 5 10

s[i]:0 2 10 -10 -5 5(s[0]=0要参与进来排序和后续比较运算)

排序后s[i]:-10 -5 0 2 5 10

|s[i]-s[i+1|]:5 5 2 3 5 ,最小2为本题答案。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #define INF 1000005
 6 using namespace std;
 7 int num[INF],sum[INF];
 8 int main()
 9 {
10     int N;
11     scanf("%d",&N);
12     for(int i=1;i<=N;i++)
13         scanf("%d",&num[i]);
14     sum[0]=0;
15     for (int i=1;i<=N;i++)
16         sum[i]+=sum[i-1]+num[i];
17     sort(sum,sum+N+1);  //注意,这里s[0]要参与排序和进行后续的比较运算。      
18     int minx=INF;
19     for(int i=0;i<N;i++)
20         if(abs(sum[i]-sum[i+1])<minx) minx=abs(sum[i]-sum[i+1]);
21     printf("%d
",minx);    
22     return 0;
23 }
原文地址:https://www.cnblogs.com/cutepota/p/12120567.html