[NOI2010]超級鋼琴 - 主席樹 - 堆
阿新 • • 發佈:2018-11-11
題目大意:問長度在[L,R]的前k大子區間的和。5e5。
題解:對每個右端點用主席樹維護其第k大即可,然後光榮MLE。
#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define INF 2000000000
#define N 500010
#define S(rt) (((rt)==NULL)?0:(rt)->s)
#define CH(rt,g) (((rt)==NULL)?NULL:(rt)->ch[g])
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x=0,s=1,ch;while(((ch=gc)<'0'||ch>'9')&&ch!='-');
if(ch^'-') x=ch^'0';else s=-1;
while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');
return s*x;
}
struct segment{
int s;segment *ch[2];
}*T[N];priority_queue< pii> q;int a[N],s[N],st[N],ed[N],cnt[N];
int build(segment* &x,segment *y,int l,int r,int p)
{
x=new segment,x->s=S(y)+1;
x->ch[0]=CH(y,0),x->ch[1]=CH(y,1);
int mid=(l+r)>>1;if(l==r) return 0;
if(p<=mid) build(x->ch[0],CH(y,0),l,mid,p);
if(mid<p) build(x->ch[1],CH(y,1),mid+1,r,p);
return 0;
}
int query(segment *x,segment *y,int l,int r,int k)
{
if(S(x)-S(y)<k) return INF;int mid=(l+r)>>1,v;if(l==r) return l;
if(k<=(v=S(CH(x,0))-S(CH(y,0)))) return query(CH(x,0),CH(y,0),l,mid,k);
return query(CH(x,1),CH(y,1),mid+1,r,k-v);
}
inline int query(int s,int t,int c,int mx) { if(s>t) return INF;return query(T[t],s?T[s-1]:NULL,1,mx,c); }
int main()
{
// freopen("data.in","r",stdin),freopen("std.out","w",stdout);
int n=inn(),k=inn(),L=inn(),R=inn(),bas=1,mx=0;lint Ans=0ll;
rep(i,1,n) a[i]=inn(),s[i]=s[i-1]+a[i],bas=max(bas,-s[i]+1),mx=max(mx,s[i]);
mx+=bas;rep(i,0,n) s[i]+=bas,build(T[i],i?T[i-1]:NULL,1,mx,s[i]);
rep(i,1,n) st[i]=max(i-R,0),ed[i]=i-L,cnt[i]=1,q.push(mp(s[i]-query(st[i],ed[i],1,mx),i));
for(int x;k;k--) x=q.top().sec,Ans+=q.top().fir,q.pop(),q.push(mp(s[x]-query(st[x],ed[x],++cnt[x],mx),x));
return !printf("%lld\n",Ans);
}