【题解】
(划分树做法)
要求出长度为l~r的前k大连续和,可以转化为k次求第i大连续和,这与划分树的作用有关时间复杂度:划分树预处理_O( n*log(n) ) +Ⅰ_O( n*log(n) ) +Ⅱ_O( k*log(n) )
【代码】
#include<stdio.h> #include<stdlib.h> typedef long long LL; struct node { int v[500005],num[500005]; }; node T[20]; int s[500005]={0},p[500005]={0},heap[500005]={0},pos[500005]={0}; int ph=0; int min(int a,int b) { if(a<b) return a; return b; } void jh(int* a,int* b) { int t=*a; *a=*b; *b=t; } void jh_heap(int a,int b) { jh(&heap[a],&heap[b]); jh(&pos[a],&pos[b]); } void kp(int low,int high) { int i=low,j=high,mid=s[(i+j)/2]; while(i<j) { while(s[i]<mid) i++; while(s[j]>mid) j--; if(i<=j) { jh(&s[i],&s[j]); i++; j--; } } if(j>low) kp(low,j); if(i<high) kp(i,high); } void build(int left,int right,int deep) { int mid=(left+right)/2,ln=left,rn=mid+1,isame=mid-left+1,same=0,i; if(left==right) return; for(i=left;i<=right;i++) if(T[deep].v[i]<s[mid]) isame--; for(i=left;i<=right;i++) { if(i==left) T[deep].num[i]=0; else T[deep].num[i]=T[deep].num[i-1]; if(T[deep].v[i]<s[mid]) { T[deep+1].v[ln++]=T[deep].v[i]; T[deep].num[i]++; } if(T[deep].v[i]>s[mid]) T[deep+1].v[rn++]=T[deep].v[i]; if(T[deep].v[i]==s[mid]) { same++; if(isame>=same) { T[deep+1].v[ln++]=T[deep].v[i]; T[deep].num[i]++; } else T[deep+1].v[rn++]=T[deep].v[i]; } } build(left,mid,deep+1); build(mid+1,right,deep+1); } int cx(int x,int y,int k,int left,int right,int deep) { int mid=(left+right)/2,before,have,b,h,tx,ty,fk=y-x+1+1-k; if(left==right) return T[deep].v[left]; if(x==left) { before=0; have=T[deep].num[y]; } else { before=T[deep].num[x-1]; have=T[deep].num[y]-T[deep].num[x-1]; } if(fk<=have)//左 { tx=left+before; ty=left+before+have-1; k=ty-tx+1+1-fk; return cx(tx,ty,k,left,mid,deep+1); } else//右 { b=x-1-left-before+1; h=y-x+1-have; tx=mid+1+b; ty=mid+1+b+h-1; k=ty-tx+1+1-(fk-have); return cx(tx,ty,k,mid+1,right,deep+1); } } void tj(int x,int t) { int i; heap[++ph]=t; pos[ph]=x; for(i=ph;i!=1;i/=2) { if(heap[i]>heap[i/2]) jh_heap(i,i/2); else return; } } void sc() { int i=1; jh_heap(1,ph); ph--; while(i*2<=ph) { i*=2; if(i+1<=ph&&heap[i+1]>heap[i]) i++; if(heap[i]>heap[i/2]) jh_heap(i,i/2); else return; } } int main() { LL ans=0; int n,k,l,r,i,x; scanf("%d%d%d%d",&n,&k,&l,&r); for(i=1;i<=n;i++) { scanf("%d",&s[i]); s[i]+=s[i-1]; T[0].v[i]=s[i]; } T[0].v[0]=0; kp(1,n); build(1,n,0); for(i=1;i<=n-l+1;i++) { p[i]=1; tj(i,cx(i+l-1,min(n,i+r-1),1,1,n,0)-T[0].v[i-1]); } for(i=1;i<=k;i++) { ans+=(LL)heap[1]; x=pos[1]; sc(); p[x]++; if((x+l-1)+p[x]-1<=min(n,x+r-1)) tj(x,cx(x+l-1,min(n,x+r-1),p[x],1,n,0)-T[0].v[x-1]); } printf("%lld",ans); return 0; }