洛谷 P2048 [NOI2010]超级钢琴(优先队列,RMQ)

传送门

我们定义$(p,l,r)=max{sum[t]-sum[p-1],p+l-1leq tleq p+r-1 }$

那么因为对每一个$p$来说$sum[p-1]$是一个定值,所以我们只要在$[p+l-1,p+r-1]$的区间里找出最大的$sum[t]$就行了,这就是一个RMQ问题,开个ST表就行了

一开始我们用优先队列存储所有的$(p,l,r)$,然后每一次取出队首更新答案

注意如果$t$被选了,答案还有可能在$t$两边的区间里,所以记得把$(p,l,t-1)$和$(p,t+1,r)$给扔进优先队列里

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cmath>
 8 #define ll long long
 9 using namespace std;
10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
11 char buf[1<<21],*p1=buf,*p2=buf;
12 inline int read(){
13     #define num ch-'0'
14     char ch;bool flag=0;int res;
15     while(!isdigit(ch=getc()))
16     (ch=='-')&&(flag=true);
17     for(res=num;isdigit(ch=getc());res=res*10+num);
18     (flag)&&(res=-res);
19     #undef num
20     return res;
21 }
22 const int N=500005,LOG=20;
23 ll sum[N],st[N][LOG];
24 int n,k,l,r;
25 void init(){
26     for(int i=1;i<=n;++i) st[i][0]=i;
27     for(int j=1;(1<<j)<=n;++j)
28     for(int i=1;i+(1<<j)-1<=n;++i){
29         int x=st[i][j-1],y=st[i+(1<<j-1)][j-1];
30         st[i][j]=sum[x]>sum[y]?x:y;
31     }
32 }
33 inline int query(int l,int r){
34     int k=log2(r-l+1);
35     int x=st[l][k],y=st[r-(1<<k)+1][k];
36     return sum[x]>sum[y]?x:y;
37 }
38 struct node{
39     int p,l,r,t;
40     node(){}
41     node(int p,int l,int r):p(p),l(l),r(r),t(query(l,r)){}
42     inline bool operator <(const node &b)const
43     {return sum[t]-sum[p-1]<sum[b.t]-sum[b.p-1];}
44 };
45 priority_queue<node> q;
46 int main(){
47 //    freopen("testdata.in","r",stdin);
48     n=read(),k=read(),l=read(),r=read();
49     for(int i=1;i<=n;++i)
50     sum[i]=read(),sum[i]+=sum[i-1];
51     init();
52     for(int i=1;i<=n;++i)
53     if(i+l-1<=n)
54     q.push(node(i,i+l-1,min(i+r-1,n)));
55     ll ans=0;
56     while(k--){
57         int p=q.top().p,l=q.top().l,r=q.top().r,t=q.top().t;
58         q.pop();
59         ans+=sum[t]-sum[p-1];
60         if(l!=t) q.push(node(p,l,t-1));
61         if(t!=r) q.push(node(p,t+1,r));
62     }
63     printf("%lld
",ans);
64     return 0;
65 }
原文地址:https://www.cnblogs.com/bztMinamoto/p/9676536.html