标签:
/* 自己yy的奇葩做法居然A了23333 不过空间好像很大 时间好像略慢..... 毕竟不是正解 前缀维护sum值 枚举区间起点 然后终点的坐标可以确定在一个范围 可持久化线段树查询区间第1大 然后放到堆里 注意每个从堆里取出来再把这个区间第2大的放进去 这里k可能减成负的 注意特判 开始wa了 还有开longlong */ #include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<algorithm> #define pa pair<int,int> #define mk make_pair #define maxn 500010 using namespace std; int n,m,l,r,k,x,root[maxn],a[maxn],s[maxn],cnt[maxn],tot; long long ans; struct node{ int sum,lc,rc; }t[maxn*20*4]; priority_queue<pa>q; int init(){ int x=0,f=1;char s=getchar(); while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} return x*f; } int Build(int S,int L,int R){ ++tot;t[tot].sum=S; t[tot].lc=L;t[tot].rc=R; return tot; } void Insert(int &root,int pre,int l,int r,int pos){ root=Build(t[pre].sum+1,t[pre].lc,t[pre].rc); if(l==r)return; int mid=l+r>>1; if(pos<=mid)Insert(t[root].lc,t[pre].lc,l,mid,pos); else Insert(t[root].rc,t[pre].rc,mid+1,r,pos); } int Query(int L,int R,int l,int r,int k){ if(l==r)return l; int mid=l+r>>1; int sum=t[t[R].lc].sum-t[t[L].lc].sum; if(k<=sum)return Query(t[L].lc,t[R].lc,l,mid,k); else return Query(t[L].rc,t[R].rc,mid+1,r,k-sum); } int main() { freopen("piano.in","r",stdin); //freopen("piano.out","w",stdout); n=init();k=init();l=init();r=init(); for(int i=1;i<=n;i++){ x=init(); s[i]=s[i-1]+x; a[i]=s[i]; } int num,pos,L,R,p,len,t; sort(a+1,a+1+n); num=unique(a+1,a+1+n)-a-1; for(int i=1;i<=n;i++){ pos=lower_bound(a+1,a+1+num,s[i])-a; Insert(root[i],root[i-1],1,num,pos); } while(!q.empty())q.pop(); for(int i=1;i+l-1<=n;i++){ L=i+l-1,R=min(n,i+r-1); len=R-L+1;++cnt[i];t=len-cnt[i]+1; pos=Query(root[L-1],root[R],1,num,t); q.push(mk(a[pos]-s[i-1],i)); } for(int i=1;i<=k;i++){ p=q.top().second; ans+=q.top().first;q.pop(); L=p+l-1,R=min(n,p+r-1); len=R-L+1;++cnt[p];t=len-cnt[p]+1; if(t<=0)continue; pos=Query(root[L-1],root[R],1,num,t); q.push(mk(a[pos]-s[p-1],p)); } cout<<ans<<endl; return 0; }
标签:
原文地址:http://www.cnblogs.com/yanlifneg/p/5858654.html