luogu P2048 [NOI2010]超級鋼琴
阿新 • • 發佈:2018-10-04
struct ace inf names return show fin 前綴和 get
傳送門
編號好評
先把所有數記個前綴和,然後對於某一個右端點\(r(r\geq L)\),能計入答案的\(l\)的範圍為\([\max(r-R,0),r-L]\)
可以開一個大根堆,先對於所有右端點\(r\),加入\(pre_r-\min(pre_{l})\),然後每次取出堆頂加入答案,彈掉堆頂,同時如果這是堆頂對應右端點減第\(k\)小的左端點的值,就把右端點減第\(k+1\)小的左端點的值加入堆中,這裏我們可以使用主席樹查詢該區間內的任意第\(k\)小值
#include<bits/stdc++.h> #define LL long long #define il inline #define re register #define db double #define eps (1e-7) using namespace std; const int N=500000+10; const LL inf=1ll<<45; il LL rd() { re LL x=0,w=1;re char ch=0; while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*w; } #define mid ((l+r)>>1) int s[N*20],ch[N*20][2],rt[N],tt; int n,kk,L,R,a[N],b[N],pp[N][3]; il void inst(int p) { rt[p]=++tt; int o1=rt[p],o2=rt[p-1],l=1,r=n; s[o1]=s[o2]+1; while(l<r) { if(a[p]<=mid) { ch[o1][0]=++tt,ch[o1][1]=ch[o2][1]; o1=ch[o1][0],o2=ch[o2][0],r=mid; } else { ch[o1][0]=ch[o2][0],ch[o1][1]=++tt; o1=ch[o1][1],o2=ch[o2][1],l=mid+1; } s[o1]=s[o2]+1; } } int quer(int o1,int o2,int l,int r,int k) { if(l==r) return b[l]; int kkk=s[ch[o1][0]]-s[ch[o2][0]]; if(k<=kkk) return quer(ch[o1][0],ch[o2][0],l,mid,k); else return quer(ch[o1][1],ch[o2][1],mid+1,r,k-kkk); } struct node { LL x; int n; node(){x=-inf;} }hp[N*3]; LL ans; int tp; il void ps(node a) { hp[++tp]=a; int nw=tp; while(nw>1&&hp[nw].x>hp[nw>>1].x) swap(hp[nw],hp[nw>>1]),nw>>=1; } il void po() { hp[1]=hp[tp],hp[tp--].x=-inf; int nw=1,p=2; while(hp[p].x>-inf) { if(hp[p+1].x>hp[p].x) ++p; if(hp[nw].x>hp[p].x) break; swap(hp[nw],hp[p]); nw=p,p<<=1; } } int q; int main() { n=rd()+1,kk=rd(),L=rd(),R=rd(); for(int i=2;i<=n;i++) a[i]=b[i]=a[i-1]+rd(); sort(b+1,b+n+1),unique(b+1,b+n+1); int nn=1; while(b[nn]<b[nn+1]) ++nn; for(int i=1;i<=n;i++) { a[i]=lower_bound(b+1,b+nn+1,a[i])-b; inst(i); } for(int i=L+1;i<=n;i++) { pp[i][0]=max(1,i-R),pp[i][1]=i-L,pp[i][2]=1; node xx; xx.x=(LL)(b[a[i]]-quer(rt[pp[i][1]],rt[pp[i][0]-1],1,n,pp[i][2])),xx.n=i; ps(xx); } for(int h=1;h<=kk;h++) { ans+=hp[1].x; int i=hp[1].n; po(); ++pp[i][2]; if(pp[i][2]>pp[i][1]-pp[i][0]+1) continue; node xx; xx.x=b[a[i]]-quer(rt[pp[i][1]],rt[pp[i][0]-1],1,n,pp[i][2]),xx.n=i; ps(xx); } printf("%lld\n",ans); return 0; }
luogu P2048 [NOI2010]超級鋼琴