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

    题面

    传送门

    Sol

    求前缀和之后,每次枚举左端点,找到相应的区间最大值,丢到堆里面
    每次取出一个就拿出来找下一个最大值再丢进去
    那么就是要求区间第(k)大,主席树就好了
    因为数组开小了和没开longlong,WA无数遍
    我太菜了太菜了太菜了

    # include <bits/stdc++.h>
    # define IL inline
    # define RG register
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(5e5 + 5);
    
    IL ll Read(){
    	RG char c = getchar(); RG ll x = 0, z = 1;
    	for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    	for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    	return x * z;
    }
    
    int n, k, L, R, a[_], rt[_], sz[_ * 20], cnt, ls[_ * 20], rs[_ * 20], o[_], len;
    ll ans;
    struct Data{
    	int v, l, kth;
    	IL bool operator <(RG Data B) const{  return v < B.v;  }
    };
    priority_queue <Data> Q;
    
    IL void Modify(RG int &x, RG int l, RG int r, RG int val){
    	sz[++cnt] = sz[x] + 1; ls[cnt] = ls[x]; rs[cnt] = rs[x]; x = cnt;
    	if(l == r) return;
    	RG int mid = (l + r) >> 1;
    	if(val <= mid) Modify(ls[x], l, mid, val);
    	else Modify(rs[x], mid + 1, r, val);
    }
    
    IL int Query(RG int A, RG int B, RG int l, RG int r, RG int kth){
    	if(l == r) return o[l];
    	RG int sum = sz[ls[A]] - sz[ls[B]], mid = (l + r) >> 1;
    	if(sum >= kth) return Query(ls[A], ls[B], l, mid, kth);
    	return Query(rs[A], rs[B], mid + 1, r, kth - sum);
    }
    
    int main(RG int argc, RG char* argv[]){
    	n = Read(); k = Read(); L = Read(); R = Read();
    	for(RG int i = 1; i <= n; ++i) a[i] = a[i - 1] + Read(), o[++len] = a[i];
    	sort(o + 1, o + len + 1); len = unique(o + 1, o + len + 1) - o - 1;
    	for(RG int i = 1; i <= n; ++i){
    		a[i] = lower_bound(o + 1, o + len + 1, a[i]) - o;
    		rt[i] = rt[i - 1];
    		Modify(rt[i], 1, len, a[i]);
    	}
    	for(RG int i = 1; i + L - 1 <= n; ++i){
    		RG int l = i + L - 1, r = min(n, i + R - 1), mx = Query(rt[r], rt[l - 1], 1, len, r - l + 1);
    		Q.push((Data){mx - o[a[i - 1]], i, r - l + 1});
    	}
    	for(RG int i = 1; i <= k; ++i){
    		RG Data x = Q.top(); Q.pop();
    		ans += x.v;
    		if(x.kth == 1) continue;
    		RG int l = x.l + L - 1, r = min(n, x.l + R - 1), mx = Query(rt[r], rt[l - 1], 1, len, x.kth - 1);
    		Q.push((Data){mx - o[a[x.l - 1]], x.l, x.kth - 1});
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    【转】 GetProcAddress()用法
    AutoCAD开发小记
    Visual Studio 2015正式版发布
    【VS2010]如何删除【附加依赖项】中“继承的值”?
    OpenCV入门指南
    Visual Studio 遇到了异常。这可能是由某个扩展导致的。
    VS2010在WIN7下安装报错“下列组件安装失败”如何解决
    获取系统日期时间的简单方法
    免费在线pdf互转工具
    应用层vc实现三种文件监视方法
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8334328.html
Copyright © 2011-2022 走看看