//常州大学新生寒假训练会试 /* 题目描述 常州大学组织了新生寒假训练一共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 ",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 ",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.
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).
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
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 ",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.
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)
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
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 ",tt,ans); 94 } 95 return 0; 96 }