一种新的想法,但30pts
查看原帖
一种新的想法,但30pts
392830
zhengbinkang楼主2023/5/21 10:49
#include<iostream>
#include<queue>
#define maxn int(5e5+5)
#define logn int(30)
#define ll long long
using namespace std;
ll pre[maxn];
int st[logn][maxn], lg[maxn];
ll n, k, L, R;
priority_queue<ll, vector<ll>, greater<int> > q;
void prest() {
	lg[0] = -1;
	for(int i = 1; i <= n; i++) {
		lg[i] = lg[i>>1]+1;
	}
	
	int x, y;
	long long ret = 0;
	for(int i = 1; i <= lg[n]; i++) {
		for(int j = 1; j+(1<<i)-1<=n; j++) {
			x = st[i-1][j]; y = st[i-1][j+(1<<(i-1))];
			st[i][j] = (pre[x] > pre[y])? x : y;
		}
	}
}
int RMQ(int lx, int rx) {
	int x = lg[rx-lx+1];
	return (st[x][lx] > st[x][rx-(1<<x)+1])?
	st[x][lx] : st[x][rx-(1<<x)+1];
}

void solve(int x, int lx, int rx) { //左端点,L,R 
	if(lx>rx) return;
	int tx = RMQ(lx, rx);
	ll ret = pre[tx]-pre[x-1];
	q.push(ret);
	while(q.size()>k) q.pop();
	if(q.size()==k && q.top() > ret) return;
	solve(x, lx, tx-1);
	solve(x, tx+1, rx);
}
int main() {
	scanf("%lld%lld%lld%lld", &n, &k, &L, &R);
	pre[0] = 0;
	for(int i = 1; i <= n; i++) {
		scanf("%lld", &pre[i]);
		pre[i]+=pre[i-1];
		st[0][i] = i;
	}
	
	prest();
   
	for(int i = 1; i+L-1<= n; i++) {
		solve(i, i+L-1, min(n, i+R-1));
	}
	long long sum = 0;
	for(int i = 1; i <= k; i++) {
		sum += q.top();
		q.pop();
	}
	printf("%lld\n", sum);
	return 0;
}

用小根堆控制答案数,全部求完再输出
开O2后WA#2,感觉是爆了但找不出问题 求调

2023/5/21 10:49
加载中...