• HDU 3415 Max Sum of Max-K-sub-sequence


    题目链接

    题目大意:

    我们有一个环状的数列,内有n个元素,现在其中找一长度不超过k的连续子序列,使值最大.

    分析:

    原数组断环为链:

    (A_1)..(A_n) = > (A_1).. (A_n A_{n+1})..(A_{n+k})

    考虑一段连续的子序列的值就是前缀和相减的形式

    我们得到前缀和数组

    (S_1)..(S_{n+k})

    考虑以i为右端点的子序列,共有k种,值分别是(S_i-S_{i-1}),(S_i-S_{i-2})...(S_i-S_{i-k})

    显然我们要在这之中找一个最大值,即在(S_{i-1}),(S_{i-2})...(S_{i-k})中找一个最小值

    问题转化成对于每个(S_i),在某一定长区间内找一最小值

    ST表,线段树均可在(O(nlogn))的时间内解决

    但是还可以更快,用单调队列

    [Code]

    
    #include <bits/stdc++.h>
    using namespace std;
    
    int read(){
    	int x=0,flag=1; char c;
    	for(c=getchar();!isdigit(c);c=getchar()) if(c=='-') flag=-1;
    	for(;isdigit(c);c=getchar()) x=((x+(x<<2))<<1)+(c^48);
    	return x*flag;
    }
    
    const int N=2e5+50;
    
    int n,k;
    int a[N];
    int s[N];
    
    int main() {
        int T=read();
        while(T--){
    	    n=read(),k=read();
    	    for(int i=1;i<=n;i++) a[i]=read();
    	    for(int i=n+1;i<=n+k+1;i++) a[i]=a[i-n];
    	    for(int i=1;i<=n+k+1;i++) s[i]=s[i-1]+a[i];
    	    
    	    int ans=-2e9;
    	    int l=-1,r=-1;
    	    
    	    deque<int> q;
    	    q.push_back(0);
    	    for(int i=1;i<=n+k+1;i++){
    		    while(!q.empty()&&i-q.front()>k) q.pop_front();
    		    if(s[i]-s[q.front()]>ans){
    			    ans=s[i]-s[q.front()];
    			    l=q.front()+1; r=i;
    			}
    			ans=max(ans,s[i]-s[q.front()]);
    		    while(!q.empty()&&s[q.back()]>=s[i]) q.pop_back();
    		    q.push_back(i);
    		}
    
            if(l>n) l-=n;
            if(r>n) r-=n;
    		
    		printf("%d %d %d
    ",ans,l,r);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    wc
    wbinfo
    wall -- 向所有人的终端发送消息
    w
    vt-is-UTF8
    vmstat
    vimtutor
    vim
    centos7
    Web 在线文件管理器学习笔记与总结(8)删除文件
  • 原文地址:https://www.cnblogs.com/zzhzzh123/p/12221843.html
Copyright © 2020-2023  润新知