P2048 [NOI2010]超级钢琴 [堆+st表]

考虑只能取长度为 [L,R] 的,然后不难想到用堆搞。

搞个前缀和的st表,里面维护的是一个 最大值的位置

struct rmq {
	int mx[N][20] ;
	void qwq(int n) {
		rep(i , 1 , n) mx[i][0] = i ;
		for(int j = 1 ; (1 << j) <= n ; j ++)
			for(int i = 1 ; i + (1 << j) - 1 <= n ; i ++) {
				int x = mx[i][j - 1] , y = mx[i + (1 << j - 1)][j - 1] ;
				mx[i][j] = sum[x] > sum[y] ? x : y ;
			}
	}
	int qry(int l , int r) {
		int k = log2(r - l + 1) ;
		int x = mx[l][k] , y = mx[r - (1 << k) + 1][k] ;
		return sum[x] > sum[y] ? x : y ;
	}
} st ;

考虑 对于任意的 \(i\) , 放进去一个 \([i+L-1 , min(i+R-1 , n)]\)

每次从中间分裂就好了,堆自动取max,这题没了
code

// by Isaunoya
#include <bits/stdc++.h>
using namespace std;

#define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
#define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
#define int long long

const int _ = 1 << 21;
struct I {
	char fin[_], *p1 = fin, *p2 = fin;
	inline char gc() {
		return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
	}
	inline I& operator>>(int& x) {
		bool sign = 1;
		char c = 0;
		while (c < 48) ((c = gc()) == 45) && (sign = 0);
		x = (c & 15);
		while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
		x = sign ? x : -x;
		return *this;
	}
	inline I& operator>>(double& x) {
		bool sign = 1;
		char c = 0;
		while (c < 48) ((c = gc()) == 45) && (sign = 0);
		x = (c - 48);
		while ((c = gc()) > 47) x = x * 10 + (c - 48);
		if (c == '.') {
			double d = 1.0;
			while ((c = gc()) > 47) d = d * 0.1, x = x + (d * (c - 48));
		}
		x = sign ? x : -x;
		return *this;
	}
	inline I& operator>>(char& x) {
		do
			x = gc();
		while (isspace(x));
		return *this;
	}
	inline I& operator>>(string& s) {
		s = "";
		char c = gc();
		while (isspace(c)) c = gc();
		while (!isspace(c) && c != EOF) s += c, c = gc();
		return *this;
	}
} in;
struct O {
	char st[100], fout[_];
	signed stk = 0, top = 0;
	inline void flush() {
		fwrite(fout, 1, top, stdout), fflush(stdout), top = 0;
	}
	inline O& operator<<(int x) {
		if (top > (1 << 20)) flush();
		if (x < 0) fout[top++] = 45, x = -x;
		do
			st[++stk] = x % 10 ^ 48, x /= 10;
		while (x);
		while (stk) fout[top++] = st[stk--];
		return *this;
	}
	inline O& operator<<(char x) {
		fout[top++] = x;
		return *this;
	}
	inline O& operator<<(string s) {
		if (top > (1 << 20)) flush();
		for (char x : s) fout[top++] = x;
		return *this;
	}
} out;
#define pb emplace_back
#define fir first
#define sec second

template < class T > inline void cmax(T & x , const T & y) {
	(x < y) && (x = y) ;
}
template < class T > inline void cmin(T & x , const T & y) {
	(x > y) && (x = y) ;
}

int n , k , L , R ;
const int N = 5e5 + 10 ;
int sum[N] ;
struct rmq {
	int mx[N][20] ;
	void qwq(int n) {
		rep(i , 1 , n) mx[i][0] = i ;
		for(int j = 1 ; (1 << j) <= n ; j ++)
			for(int i = 1 ; i + (1 << j) - 1 <= n ; i ++) {
				int x = mx[i][j - 1] , y = mx[i + (1 << j - 1)][j - 1] ;
				mx[i][j] = sum[x] > sum[y] ? x : y ;
			}
	}
	int qry(int l , int r) {
		int k = log2(r - l + 1) ;
		int x = mx[l][k] , y = mx[r - (1 << k) + 1][k] ;
		return sum[x] > sum[y] ? x : y ;
	}
} st ;
struct element {
	int o , l , r , t ;
	element() {}
	element(int _o , int _l , int _r) : o(_o) , l(_l) , r(_r) , t(st.qry(_l , _r)) {}
	bool operator < (const element & other) const {
		return sum[t] - sum[o - 1] < sum[other.t] - sum[other.o - 1] ;
	}
};

priority_queue < element > q ;
signed main() {
#ifdef _WIN64
	freopen("testdata.in" , "r" , stdin) ;
#endif
	in >> n >> k >> L >> R ;
	rep(i , 1 , n) {
		in >> sum[i] ;
		sum[i] += sum[i - 1] ;
	}
	st.qwq(n) ;
	rep(i , 1 , n) 
		if(i + L - 1 <= n) q.push(element(i , i + L - 1 , min(i + R - 1 , n))) ;
	int ans = 0 ;
	rep(i , 1 , k) {
		int o = q.top().o , l = q.top().l , r = q.top().r , t = q.top().t ; q.pop() ;
		ans += sum[t] - sum[o - 1] ;
		if(l != t) q.push(element(o , l , t - 1)) ;
		if(r != t) q.push(element(o , t + 1 , r)) ;
	}
	out << ans << '\n' ;
	return out.flush(), 0;
}
posted @ 2020-01-15 20:27  _Isaunoya  阅读(103)  评论(0编辑  收藏  举报