牛客网【每日一题】3月27日 数学考试
題號 NC15553
名稱 數學考試
來源 2018年長沙理工大學第十三屆程序設計競賽
鏈接:https://ac.nowcoder.com/acm/problem/15553
來源:牛客網
試題傳送門
時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 32768K,其他語言65536K 64bit IO Format:
%lld
題目描述
今天qwb要參加一個數學考試,這套試卷一共有n道題,每道題qwb能獲得的分數為ai,qwb并不打算把這些題全做完,
他想選總共2k道題來做,并且期望他能獲得的分數盡可能的大,他準備選2個不連續的長度為k的區間,
即[L,L+1,L+2,…,L+k-1],[R,R+1,R+2,…,R+k-1](R >= L+k)。
輸入描述:
第一行一個整數T(T<=10),代表有T組數據 接下來一行兩個整數n,k,(1<=n<=200,000),(1<=k,2k <= n)
接下來一行n個整數a1,a2,…,an,(-100,000<=ai<=100,000)
輸出描述:
輸出一個整數,qwb能獲得的最大分數
示例1
輸入
輸出
6 7題解:
題意就是求不想交的前綴與后綴和的最大值
第一反應是線段樹(畢竟是有關區間查詢 ) ,不過仔細想想也不能這么麻煩(打線段樹不累嗎? ) ,不過也有大佬用線段樹做的。
根據題意知道前綴與后綴長度一樣,依據樸素的原則單純打暴力肯定不行,需要優化優化,怎么優化呢?
我們先求出所有前綴和q[]
然后按照給定前后綴的長度k,求出每個k長區間的和
比如 -1 0 2 -1 -1 2 3 -1 k=2;
每個k長區間的和為:w[]-1 2 1 -2 1 5 2
我們所要求的最大值max=dp1+dp2
dp1是前綴和最大值
dp2是后綴和最大值
那其實就是在w中取一個dp1再取一個dp2,使他們和最大
但注意前綴與后綴不能相交和相連
方法一:
稍微處理下,可以先選后綴,然后前綴的范圍就是去除已選的后綴,在里面取最大的前綴
maxx=(q[i]-q[i-k])+max(q[1],q[2],q[3]…q[i-k-1])
(q[i]-q[i-k])后綴和
max(q[1],q[2],q[3]…q[i-k-1])最大的前綴
然后求出maxx的最大值情況
誒,這不就是線性dp嗎!wok做完才注意到
方法二:
求出前綴和所能取到的最大值(從頭開始),放入數組w1
求出后綴和所能取到的最大值(從尾開始),放入w2中
然后再一個循環,求出w1[i]與w2[i+1](即當前位i的前綴和與排在i之后的最大后綴和之和)的最大值
代碼一
代碼二
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> typedef long long ll; using namespace std; const int inf=2e5+4; ll a[inf]; ll q[inf]; ll w[inf]; ll w1[inf],w2[inf]; int main() {int t;cin>>t;int n,k;ll cnt;while(t--){cin>>n>>k;for(int i=1;i<=n;i++){cin>>cnt;q[i]=q[i-1]+cnt; }memset(w1,-128,sizeof(w1));memset(w2,-128,sizeof(w2));cnt=-1e10;for(int i=k;i<=n;i++){w[i]=q[i]-q[i-k];} for(int i=k;i<=n-k+1;i++)w1[i]=w[i]>w1[i-1]?w[i]:w1[i-1];for(int i=n-k+1;i>=k+1;i--)w2[i]=w2[i+1]>w[i+k-1]?w2[i+1]:w[i+k-1];for(int i=k;i<=n-k+1;i++){if(w2[i+1]+w1[i]>cnt)cnt=w2[i+1]+w1[i];}cout<<cnt<<endl;}return 0; }對了還有變形的問題:
(等晚上有空再想吧)
總結
以上是生活随笔為你收集整理的牛客网【每日一题】3月27日 数学考试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么应对ddos攻击(怎么举报DDoS攻
- 下一篇: 小G的项链(Manacher)