社区讨论

求调 悬一关

P2048[NOI2010] 超级钢琴参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mlhgc7fq
此快照首次捕获于
2026/02/11 11:10
上周
此快照最后确认于
2026/02/11 13:25
上周
查看原帖
本人没学过ST表。。。
我用的线段树维护区间最大值。
query 查的是最大值下表。
CPP
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int n,k,l,r,a[N],sum[N],ans;
struct node_{
	int i,lp,rp,o,val;
	friend bool operator<(node_ a,node_ b){
		return a.val<b.val;
	}
};
struct node{
	int l,r,mx,mxid;
}t[N*4];
void pushup(int rt){
	if(t[rt].mx<t[rt<<1].mx) t[rt].mx=t[rt<<1].mx,t[rt].mxid=t[rt<<1].mxid;
	if(t[rt].mx<t[rt<<1|1].mx) t[rt].mx=t[rt<<1|1].mx,t[rt].mxid=t[rt<<1|1].mxid;
	return;
}
void init(int l,int r,int rt=1){
	t[rt].l=l,t[rt].r=r;
	if(l==r){
		t[rt].mx=a[l],t[rt].mxid=l;
		return;
	}
	int mid=(l+r)>>1;
	init(l,mid,rt<<1);
	init(mid+1,r,rt<<1|1);
	pushup(rt);
	return;
}
int query(int l,int r,int rt=1){
	if(t[rt].l>=l&&t[rt].r<=r) return t[rt].mxid;
	int ans=-9e18,id=0,mid=(t[rt].l+t[rt].r)>>1;
	if(l<=mid){
		int x=query(l,r,rt<<1);
		if(ans<a[x]) ans=a[x],id=x;
	}
	if(r>mid){
		int x=query(l,r,rt<<1|1);
		if(ans<a[x]) ans=a[x],id=x;
	}
	return id;
}
priority_queue <node_> q;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>k>>l>>r;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];
	}
	init(1,n);
	for(int i=1;i<=n-l+1;i++){
		int lp=i+l-1,rp=min(i+r-1,n),o=query(lp,rp),val=sum[o]-sum[i-1];
		q.push({i,lp,rp,o,val});
	}
	while(k--){
		node_ t=q.top();
		q.pop();
		ans+=t.val;
		int o1=query(t.lp,t.o-1),o2=query(t.o+1,t.rp);
		q.push({t.i,t.lp,t.o-1,o1,sum[o1]-sum[t.i-1]});
		q.push({t.i,t.o+1,t.rp,o2,sum[o2]-sum[t.i-1]});
	}
	cout<<ans;
	return 0;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...