0
点赞
收藏
分享

微信扫一扫

超级钢琴 RMQ & 堆 & 贪心(手写二叉堆)

文风起武 2022-03-17 阅读 31

原题链接

#include <iostream>
#include <algorithm>


using namespace std;

const int N = 5e5 + 5;
int sut[N][20];
int sum[N];
struct Node {
	int o, l, r, w;
	bool operator < (const Node &he) const {
		return sum[this->o] - sum[this->w] < sum[he.o] - sum[he.w];
	}
	inline int get() {
		return sum[this->o] - sum[this->w];
	}
};

template<typename T, typename _Compare = less<T> >
class Heap {
	T *tr;
    int size, temp;
	_Compare cmp;
public :
	Heap(int MaxSize) {
		tr = new T[MaxSize * 2];
		size = 0;
	}
	inline void push(const T &vue) {
		tr[++ size] = vue;
	}
	inline void down(int u) {
		while ((temp = u << 1) <= size) {
			if (temp < size && cmp(tr[temp], tr[temp | 1])) ++ temp;
			if (cmp(tr[u], tr[temp])) swap(tr[u], tr[temp]), u = temp;
			else break;
		}
	}
	inline void up(int u) {
		while ((temp = u >> 1) && cmp(tr[temp], tr[u])) 
			swap(tr[temp], tr[u]), u = temp;
	}
	inline void insert(const T &vue) {
		tr[++ size] = vue;
		up(size);
	}
	inline void build() {
		for (int i = size >> 1; i; -- i) down(i);
	}
	inline T pop() {
		T top = tr[1];
		tr[1] = tr[size --];
		down(1);
		return top;
	}
};

char Log2[N];
int query(int x, int y) {
	return sum[x] < sum[y] ? x : y;
}
int MaxElement(int _L, int _R) {
	int L2_ = Log2[_R - _L + 1];
	return query(sut[_L][L2_], sut[_R + 1 - (1 << L2_)][L2_]);
}
void GetST(int Len) {
	for (int i = 2; i <= Len; ++ i) Log2[i] = Log2[i >> 1] + 1;
	int Len_1 = Len + 1;
	for (int i = 1, k = 0; i <= Log2[Len]; ++ i, ++ k) {
		int Mlie = 1 << i, Mlke = 1 << k; 
		for (int j = 0; j + Mlie <= Len_1; ++ j) {
			//sut[j][i] = max(sut[j][k], sut[j + Mlke][k]);
			sut[j][i] = query(sut[j][k], sut[j + Mlke][k]);
		}
	}	
}

signed main() {
	int n, k, L, R, num;
	long long res = 0;
	scanf("%d %d %d %d", &n, &k, &L, &R);
	for (int i = 1; i <= n; ++ i) scanf("%d", &num), sum[i] = sum[i - 1] + num, sut[i][0] = i;
	GetST(n);
	Heap<Node> Q(max(n, k));
	for (int i = L; i <= n; ++ i) {
		int r = i - L, l = max(0, i - R);
		Q.push(Node{i, l, r, MaxElement(l, r)});
	}
	Q.build();
	while (k --) {
		Node data = Q.pop();
		res += data.get();
		if (data.w != data.l) Q.insert(Node{data.o, data.l, data.w - 1, MaxElement(data.l, data.w - 1)}); 
		if (data.w != data.r) Q.insert(Node{data.o, data.w + 1, data.r, MaxElement(data.w + 1, data.r)});
	}
	return cout << res, 0;
}
举报

相关推荐

0 条评论