最大字段和

 

 

 

//常州大学新生寒假训练会试
/*

题目描述 
常州大学组织了新生寒假训练一共N天,每天训练可以获得的训练效果是Ei。但是如果连续训练超过K天,萌新们会受不了而被劝退。
现在负责人想知道,如何安排能保证萌新不会被劝退并且能获得最大的训练效果。
输入描述:
第一行:两个用空格隔开的整数:N和K,1≤N≤100000,1≤K≤N
第二行到N+1行:第i+1行有一个整数,表示第N天的训练效果是Ei,(0 <= Ei <= 1,000,000,000)
输出描述:
第一行:单个整数,表示最大的能力之和
示例1
输入
复制
5 2 
1
2
3
4 
5
输出
复制
12
说明
(除了第三天以外每天都在训练,总训练效果为1+2+4+5=12)
备注:
1≤n≤100,000
*/


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <string>
#include <deque>
using namespace std;
#define  ll long long 
#define  N 100009
#define  gep(i,a,b)   for(int  i=a;i<=b;i++)
#define  gepp(i,a,b)  for(int  i=a;i>=b;i--)
#define  gep1(i,a,b)  for(ll i=a;i<=b;i++)
#define  gepp1(i,a,b) for(ll i=a;i>=b;i--)    
#define  mem(a,b)  memset(a,b,sizeof(a))
int  n,k,st,ed;
ll a[N],q[N],dp[N];
//dp[i]  :第i天不训练带来的最小损失(逆向思维)
int  main()
{
    scanf("%d%d",&n,&k);
    ll sum=0;
    gep(i,1,n)
    {
        scanf("%lld",&a[i]);
        sum+=a[i];
    }
    //维护一个单调队列
    gep(i,1,n)
    {
        
        while(st<=ed&&dp[q[ed]]>dp[i-1])  ed--;      
        while(q[st]<i-k-1) st++;
        q[++ed]=i-1;
        dp[i]=dp[q[st]]+a[i];//队首最小
    }
    ll ans=0;
    //例如  dp[4]=a[4]+a[1],dp[5]=a[5]+a[2]
    gep(i,n-k,n){//必须从n-k开始,才能保证天数不超过k天
        ans=max(ans,sum-dp[i]);
    }
    printf("%lld\n",ans);
    return  0;
}

 

 

最大子序和

题目限制

时间限制 内存限制 评测方式 题目来源
1000ms 131072KiB 标准比较器 Local

题目描述

输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。

例如 1,-3,5,1,-2,3

当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6

输入格式

第一行两个数n,m
第二行有n个数,要求在n个数找到最大子序和

输出格式

一个数,数出他们的最大子序和

提示

数据范围:
100%满足n,m<=300000

样例数据

输入样例 #1输出样例 #1
6 4
1 -3 5 1 -2 3
7

 

 

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <string>
 7 #include <deque>
 8 using namespace std;
 9 #define  ll long long 
10 #define  N 300009
11 const ll inf=9e18;
12 #define  gep(i,a,b)   for(int  i=a;i<=b;i++)
13 #define  gepp(i,a,b)  for(int  i=a;i>=b;i--)
14 #define  gep1(i,a,b)  for(ll i=a;i<=b;i++)
15 #define  gepp1(i,a,b) for(ll i=a;i>=b;i--)    
16 #define  mem(a,b)  memset(a,b,sizeof(a))
17 int  n,k,st,ed;
18 ll a[N],q[N],dp[N],sum[N];
19 int  main()
20 {
21     scanf("%d%d",&n,&k);
22     gep(i,1,n)
23     {
24         scanf("%lld",&a[i]);
25         sum[i]=sum[i-1]+a[i];
26     }
27     //维护一个单调队列
28     gep(i,1,n)
29     {       
30         while(st<=ed&&sum[q[ed]]>sum[i-1])  ed--;
31         while(st<=ed&&q[st]<i-k) st++;//为i服务的
32         q[++ed]=i-1;//要非空区间
33         dp[i]=sum[i]-sum[q[st]];//队首最小
34     }
35     ll ans=-inf;
36     gep(i,1,n){
37         ans=max(ans,dp[i]);
38     }
39     printf("%lld\n",ans);
40     return  0;
41 }

 

 

 

 

/HDU  3415

Max Sum of Max-K-sub-sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9408    Accepted Submission(s): 3472


Problem Description
Given a circle sequence A[1],A[2],A[3]......A[n]. Circle sequence means the left neighbour of A[1] is A[n] , and the right neighbour of A[n] is A[1].
Now your job is to calculate the max sum of a Max-K-sub-sequence. Max-K-sub-sequence means a continuous non-empty sub-sequence which length not exceed K.
 

 

Input
The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. 
Then T lines follow, each line starts with two integers N , K(1<=N<=100000 , 1<=K<=N), then N integers followed(all the integers are between -1000 and 1000).
 

 

Output
For each test case, you should output a line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the minimum start position, if still more than one , output the minimum length of them.
 

 

Sample Input
4 6 3 6 -1 2 -6 5 -5 6 4 6 -1 2 -6 5 -5 6 3 -1 2 -6 5 -5 6 6 6 -1 -1 -1 -1 -1 -1
 

 

Sample Output
7 1 3 7 1 3 7 6 2 -1 1 1
 

 

Author
shǎ崽@HDU
 

 

Source
 

 

Recommend
lcy   |   We have carefully selected several similar problems for you:  3423 3417 3418 3419 3421 
 
 
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <string>
 7 #include <deque>
 8 #include <set>
 9 #include <queue>
10 using namespace std;
11 #define  ll long long 
12 #define  N 200009
13 #define  gep(i,a,b)   for(int  i=a;i<=b;i++)
14 #define  gepp(i,a,b)  for(int  i=a;i>=b;i--)
15 #define  gep1(i,a,b)  for(ll i=a;i<=b;i++)
16 #define  gepp1(i,a,b) for(ll i=a;i>=b;i--)    
17 #define  mem(a,b)  memset(a,b,sizeof(a))
18 #define  P  pair<int,int>u+
19 const ll inf=9e18;
20 int  n,k,st,ed;
21 ll a[N],q[N],sum[N];
22 int t;
23 int  main()
24 {
25     scanf("%d",&t);
26     while(t--){
27     scanf("%d%d",&n,&k);
28     sum[0]=0;//不用mem(sum,0)
29     gep(i,1,n)
30     {
31         scanf("%lld",&a[i]);
32         sum[i]=sum[i-1]+a[i];
33     }   
34     gep(i,n+1,n+k-1)//环状到n+k-1就可以了
35     {
36         sum[i]=sum[i-1]+a[i-n];
37     }
38     //不按照上面求前缀和会超时
39     ll ans=-inf;
40     ll l,r;
41     st=0;
42     ed=0;
43     mem(q,0);
44     //上面三行代码不能少
45     gep1(i,1,n+k-1)
46     {        
47         
48         while(st<=ed&&sum[q[ed]]>sum[i-1])  ed--;
49         while(st<=ed&&q[st]<i-k) st++;    
50         q[++ed]=i-1; 
51         if(ans<sum[i]-sum[q[st]]){
52         ans=sum[i]-sum[q[st]];
53         l=q[st]+1;
54         r=i>n?i%n:i;//r可能大于n
55         //当出现dp[i]都是最大值时,一定是i小的符合条件
56         // 0 2 3 0                         
57         }        
58     }
59     printf("%lld %lld %lld\n",ans,l,r);
60     }
61     return  0;
62 }

 

 

 

//HDU    6444

Neko's loop

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1420    Accepted Submission(s): 328


Problem Description
Neko has a loop of size n.
The loop has a happy value ai on the i−th(0≤i≤n−1) grid. 
Neko likes to jump on the loop.She can start at anywhere. If she stands at i−th grid, she will get ai happy value, and she can spend one unit energy to go to ((i+k)modn)−th grid. If she has already visited this grid, she can get happy value again. Neko can choose jump to next grid if she has energy or end at anywhere. 
Neko has m unit energies and she wants to achieve at least s happy value.
How much happy value does she need at least before she jumps so that she can get at least s happy value? Please note that the happy value which neko has is a non-negative number initially, but it can become negative number when jumping.
 

 

Input
The first line contains only one integer T(T≤50), which indicates the number of test cases. 
For each test case, the first line contains four integers n,s,m,k(1≤n≤104,1≤s≤1018,1≤m≤109,1≤k≤n).
The next line contains n integers, the i−th integer is ai−1(−109≤ai−1≤109)
 

 

Output
For each test case, output one line "Case #x: y", where x is the case number (starting from 1) and y is the answer.
 

 

Sample Input
2 3 10 5 2 3 2 1 5 20 6 3 2 3 2 1 5
 

 

Sample Output
Case #1: 0 Case #2: 2
 

 

Source
 

 

Recommend
chendu   |   We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 
 
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <utility>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <queue>
 9 #include <stack>
10 using namespace std;
11 #define max(x,y) x>=y?x:y
12 #define lowbit(x) x&(-x)
13 #define ll long long 
14 #define ph  push_back
15 #define   N 100007//因为后面有3*n ,那么最好N 要大与3*n
16 const ll inf =9e18;
17 int t;
18 ll n,m,s,k,a[N],q[N],sum[N];
19 vector<ll>ve[N];
20 bool vis[N];
21 ll solve(int x,int n,ll m){//m  : ll
22 ll ans=0;
23 // ll q[N],sum[N]:是错的,因为局部变量必须初始化
24 for(int i=0;i<=3*n;i++){
25     sum[i]=0;
26     q[i]=0;
27 }
28 for(int i=1;i<=n;i++){
29     sum[i]=sum[i+n]=sum[i+2*n]=ve[x][i-1];
30 }    
31 for(int i=1;i<=3*n;i++) sum[i]=sum[i-1]+sum[i];//要加到3*n
32 int st=0,ed=0;
33 for(int i=1;i<=3*n;i++)//n+ans2(ans2<=2*n)<=3*n
34 {
35     while(st<=ed&&sum[i-1]<sum[q[ed]]) ed--;
36     while(st<=ed&&i-q[st]>m) st++;//i-q[st]>m 
37     q[++ed]=i-1;//加的是i-1
38     ans=max(ans,sum[i]-sum[q[st]]);
39 }
40 return ans;
41 }
42 
43 int main(){
44     scanf("%d",&t);
45     for(int tt=1;tt<=t;tt++)
46     {
47         scanf("%lld%lld%lld%lld",&n,&s,&m,&k);
48         for(int i=0;i<N;i++) {
49             vis[i]=0;
50             ve[i].clear();//每次都要清空
51         }
52         for(int i=0;i<n;i++){
53             scanf("%lld",&a[i]);
54         }
55         int cnt=0;
56         for(int i=0;i<n;i++)
57         {
58             if(!vis[i])//不然cnt 会不断加
59             {
60                 for(int j=i;!vis[j];j=(j+k)%n)//只要在遇到vis[j]==1就该结束循环了
61                 {
62                     vis[j]=1;
63                     ve[cnt].ph(a[j]);
64                 }
65                 cnt++;                
66             }
67         }
68         ll ans=-inf;
69         for(int i=0;i<cnt;i++)
70         {
71             ll tmp=0;
72             int l=ve[i].size();
73             for(int j=0;j<l;j++) tmp+=ve[i][j];//刚开始int i
74             ll res=solve(i,l,m);//如果tmp<0,那么跑个不大于m的……即可
75             ans=max(ans,res);    
76             if(tmp<0) continue;
77             ll ans1=m/l;
78             ll ans2=m%l;
79             if(ans1>=1) {//只要后面还有循环节,且>0就可以全取了
80                 ans2+=l;//那么最后一个循环要特判
81             }
82             /*
83             例如 :
84             5 1000 5 1
85             1 1 -1 -1 1
86             正确的为 997,不是999
87             */
88             tmp=tmp*(max(ans1-1,0ll));//ans1==1可能
89             res=max(res,tmp+solve(i,l,ans2));
90             ans=max(ans,res);
91         }
92         ans=max(0ll,s-ans);
93         printf("Case #%d: %lld\n",tt,ans);
94     }
95     return 0;
96 }

 

posted on 2018-07-16 15:37  cltt  阅读(195)  评论(0)    收藏  举报

导航