zoukankan      html  css  js  c++  java
  • 超级钢琴

    题意

    给定一个序列,定义和弦为长度在[L,R]上的连续元素集,其值为元素和。求最大的前k个和弦值之和。


    思路

    暴力思路是显然的:枚举左端点,然后依次枚举右端点得到最大值。

    考虑优化:对于每一个左端点,能得到的最大值应该为$$max{sum[j]}-sum[chosen_point]$$

    求最大值的过程可以使用st表优化,然后放到堆里即可。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T>inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write (T x) {
    		if (x<0) putchar('-'),x*=-1;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Project {
    	#define int long long
    	
    	const int N=500500;
    	
    	int n,k,L,R,ans;
    	int st[N][20];
    	int sum[N];
    	struct node {
    		int val,lpos,rpos,r;
    		node () {}
    		node (int _v,int _l,int _r,int _rr) : val(_v),lpos(_l),rpos(_r),r(_rr) {}
    		friend inline bool operator < (const node x,const node y) {
    			return x.val<y.val;
    		}
    	};
    	priority_queue<node> q;
    	
    	inline int min (int a,int b) {
    		return (sum[a]<sum[b])?a:b;
    	}
    	inline int query (int l,int r) {
    		if (l>r) return -1;
    		int x=log2(r-l+1);
    		return min(st[l][x],st[r-(1<<x)+1][x]);
    	}
    
    	inline void MAIN () {
    		read(n),read(k),read(L),read(R);
    		for (register int i=1; i<=n; ++i) {
    			read(sum[i]),sum[i]+=sum[i-1],st[i][0]=i;
    		}
    		for (register int i=1; (1<<i)<=n; ++i) {
    			for (register int j=0; (1<<i)+j-1<=n; ++j) {
    				st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
    			}
    		}
    		for (register int i=L; i<=n; ++i) {
    			int tmp=query(max(0ll,i-R),i-L);
    			q.push(node(sum[i]-sum[tmp],max(i-R,0ll),i-L,i));
    		}
    		for (register int i=1; i<=k; ++i) {
    			node now=q.top();q.pop(),ans+=now.val;
    			int tmp=query(now.lpos,now.rpos),s=query(now.lpos,tmp-1),t=query(tmp+1,now.rpos);
    			if (s!=-1) q.push(node(sum[now.r]-sum[s],now.lpos,tmp-1,now.r));
    			if (t!=-1) q.push(node(sum[now.r]-sum[t],tmp+1,now.rpos,now.r));
    		}
    		write(ans);
    	}
    	
    	#undef int
    }
    
    int main () {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
    
  • 相关阅读:
    visual studio 2010 在使用带namespace友元模板函数声明时的bug
    Windows同步对象Event和Linux的条件变量
    从密码学角度看TX常用的TEA加密算法
    SHA1和MD5算法详解和源码
    java 运行机制和环境搭建学习 java 归纳(1)
    循环结构学习 java 归纳(3)
    数组学习 java 归纳(4)
    条件选择结构学习 java 归纳(2)
    JavaWeb 参数
    新博客
  • 原文地址:https://www.cnblogs.com/ilverene/p/11521483.html
Copyright © 2011-2022 走看看