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

    一个很经典的做法。
    \(k\)个最值的求法,先对每个元素进行最操作,再对堆顶进行次操作丢入堆。
    考虑怎么进行次操作。

    每次把可操作的区间按最操作的位置切开。

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define ll long long 
    #define N 500005
    
    inline ll read(){
    	ll ans = 0,f = 1;
    	char a = getchar();
    	while((a != '-') && !(a <= '9' && a >= '0'))
    	a = getchar();
    	if(a == '-')
    	f = -1,a = getchar();
    	while(a <= '9' && a >='0')
    	ans = (ans << 3) + (ans << 1) + (a - '0'),a = getchar();
    	return ans * f;
    }
    
    ll num[N],sum[N];
    ll n,k,l,r;
    
    ll v[N << 2];
    ll s[N << 2];
    
    struct P{
    	int li,ri,t,x,v;
    };
    
    std::priority_queue<P>QWQ;
    
    bool operator < (P a,P b){
    	return a.v < b.v;
    }
    
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    #define mid ((l + r) >> 1)
    
    inline void build(int u,int l,int r){
    	if(l == r){
    		v[u] = sum[l];
    		s[u] = l;
    		return ;
    	} 
    	build(ls(u),l,mid);
    	build(rs(u),mid + 1,r);
    	v[u] = std::min(v[ls(u)],v[rs(u)]);
    	if(v[u] == v[ls(u)])
    	s[u] = s[ls(u)];
    	else
    	s[u] = s[rs(u)];
    }
    
    inline ll q(int u,int l,int r,int tl,int tr){
    	if(tl <= l && r <= tr)
    	return u;
    	ll ans1 = 0 , ans2 = 0;
    	if(tl <= mid)
    	ans1 = q(ls(u),l,mid,tl,tr);
    	if(tr > mid)
    	ans2 = q(rs(u),mid + 1,r,tl,tr);
    	if(v[ans1] < v[ans2])
    	return ans1;
    	else
    	return ans2;
    }
    
    
    int main(){
    	v[0] = 1e18;
    	scanf("%lld%lld%lld%lld",&n,&k,&l,&r);
    	for(int i = 1;i <= n;++i)
    	num[i] = read(),sum[i] = sum[i - 1] + num[i];
    	build(1,0,n);
    	for(int i = l;i <= n;++i){
    		P a;
    		a.li = std::max((ll)0,i - r);
    		a.ri = i - l;
    		a.t  = s[q(1,0,n,a.li,a.ri)];
    		a.x = i;
    		a.v = sum[i] - sum[a.t];
    		QWQ.push(a);
    	}
    //	for(int i = 1;i <= n;++i)
    //	std::cout<<sum[i]<<" ";
    //	puts("");
    	ll ans = 0;
    	for(int i = 1;i <= k;++i){
    		P a = QWQ.top();
    		QWQ.pop();
    		ans += a.v;
    		P b;
    		b.li = a.li; 
    		b.ri = a.t - 1;
    		if(b.li <= b.ri){
    			b.t = s[q(1,0,n,b.li,b.ri)];
    			b.x = a.x;
    			b.v = sum[b.x] - sum[b.t];
    			QWQ.push(b);
    		}
    		b.li = a.t + 1; 
    		b.ri = a.ri;
    		if(b.li <= b.ri){
    			b.t = s[q(1,0,n,b.li,b.ri)];
    			b.x = a.x;
    			b.v = sum[b.x] - sum[b.t];
    			QWQ.push(b);
    		}		
    	}
    	std::cout<<ans<<std::endl;
    
    
  • 相关阅读:
    OneNote2007产品密钥及激活方法
    穿着马甲的编码方式链式
    String 转换NameValueCollection 的方法 , 这是原创 嘎嘎
    TransactionScope分布式事务无法使用时, 配置并启动 MSDTC 的解决方案
    Spirit越狱3.1.3/3.2固件(Windows)
    智能感知 不正常的解决方法
    HttpHandler HttpModule入门篇
    Microsoft.Practices.Unity依赖注入使用实例
    ViewEngine 深入解析与应用实例
    打开chm文件提示“已取消到该网页的导航”的解决方案
  • 原文地址:https://www.cnblogs.com/dixiao/p/15098880.html
Copyright © 2011-2022 走看看