首页 > 代码库 > 超级钢琴 2010年NOI

超级钢琴 2010年NOI

/*自己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 500010using 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;}

 

超级钢琴 2010年NOI