最大字段和

 

 

 

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

题目描述 
常州大学组织了新生寒假训练一共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;
}

 

 

Joy OI /  题目列表 /

最大子序和

题目限制

时间限制内存限制评测方式题目来源
1000ms131072KiB标准比较器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 ith(0in1) grid. 
Neko likes to jump on the loop.She can start at anywhere. If she stands at ith 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(T50), which indicates the number of test cases. 
For each test case, the first line contains four integers n,s,m,k(1n104,1s1018,1m109,1kn).
The next line contains n integers, the ith integer is ai1(109ai1109)
 

 

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 }

 

转载于:https://www.cnblogs.com/tingtin/p/9317936.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值