码迷,mamicode.com
首页 > 其他好文 > 详细

超级钢琴 2010年NOI

时间:2016-09-10 08:55:42      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:

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

 

超级钢琴 2010年NOI

标签:

原文地址:http://www.cnblogs.com/yanlifneg/p/5858654.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!