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\n", ans);
	return 0;
}

posted @ 2018-01-23 10:28  Cyhlnj  阅读(159)  评论(0编辑  收藏  举报