HDU3415 Max Sum of Max-K-sub-sequence

  原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=3415

  【题目分析】

   因为序列是环状的,所以可以在序列后面复制一段(或者复制前 k 个数字)。如果用 s[i]来表示复制过后的序列的前 i 个数的和,那么任意一个子序列[i..j]的和就等于[j]-s[i-1]。对于每一个 j,用 s[j]减去最小的一个 s[i](i>=j-k+1)就可以得到以 j 为终点长度不大于 k 的和最大的序列了。将原问题转化为这样一个问题后,就可以用单调队列解决了。

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 #define N 200005
 4 #define INF 1000000000
 5 int a[N], sum[N], q[N];
 6 
 7 int main()
 8 {
 9     int n, k, max, i, head, tail, x, y, cas;
10     scanf("%d", &cas);
11     while(cas --)
12     {
13         scanf("%d%d", &n, &k);
14         for(i = 1; i <= n; i ++)
15         {
16             scanf("%d", &a[i]);
17             sum[i] = sum[i - 1] + a[i];
18         }
19         for(i = n + 1; i < n + k; i ++)
20             sum[i] = sum[i - 1] + a[i - n];
21             
22         max = -INF;
23         for(head = tail = 0, i = 1; i < n + k; i ++)
24         {
25             while(head < tail && q[head] < i - k)
26                 head ++;
27             while(head < tail && sum[i - 1] < sum[q[tail - 1]])
28                 tail --;
29             q[tail ++] = i - 1;
30             if(sum[i] - sum[q[head]] > max)
31             {
32                 max = sum[i] - sum[q[head]];
33                 x = q[head] + 1;
34                 y = i;
35             }
36         }
37         printf("%d %d %d\n", max, x, y > n ? y - n : y);
38     }
39     return 0;
40  }

你可能感兴趣的:(sequence)