• NOI2010 : 超级钢琴


    求出前缀和

    对于每个结尾i,设现在取的区间是[j+1,i],则i-R<=j<=i-L,取出该区间sum[j]的最小值,将sum[i]-sum[j]放入堆中

    建立一个大根堆,每次取出堆顶元素,将排名k+1,将sum[i]-区间第k小值放入堆中

    求区间第k小可以用主席树

    直到取满K次为止

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #define N 500010
    #define M 10000000
    using namespace std;
    int n,i,j,K,L,R,sum[N],b[N],l[M],r[M],val[M],root[N],tot;long long ans;
    inline void read(int&a){
      char c;bool f=0;a=0;
      while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
      if(c!='-')a=c-'0';else f=1;
      while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
      if(f)a=-a;
    }
    inline int lower(int x){
      int l=1,r=n,mid,t;
      while(l<=r)if(b[mid=(l+r)>>1]<x)l=mid+1;else r=(t=mid)-1;
      return t;
    }
    int ins(int x,int a,int b,int c){
      int y=++tot;
      val[y]=val[x]+1;
      if(a==b)return y;
      int mid=(a+b)>>1;
      if(c<=mid)l[y]=ins(l[x],a,mid,c),r[y]=r[x];else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c);
      return y;
    }
    inline int kth(int x,int y,int k){
      if(val[y]-val[x]<k)return 0;
      int a=1,b=n,mid,t;
      while(1){
        if(a==b)return a;
        t=val[l[y]]-val[l[x]];mid=(a+b)>>1;
        if(k<=t)b=mid,x=l[x],y=l[y];else a=mid+1,k-=t,x=r[x],y=r[y];
      }
    }
    struct node{
      int x,l,r,k,i;
      node(){}
      node(int _i,int _l,int _r,int _k){i=_i;l=_l;r=_r;k=_k;x=sum[i]-b[kth(root[l],root[r],k)];}
      node(int _i,int _k){i=_i;l=max(i-R-1,0);r=max(i-L,0);k=_k;x=sum[i]-b[kth(root[l],root[r],k)];}
      bool operator<(const node&b)const{return x<b.x;}
    }tmp;
    priority_queue<node>H;
    int main(){
      for(read(n),read(K),read(L),read(R),n++,i=2;i<=n;i++)read(j),sum[i]=sum[i-1]+j;
      for(b[0]=600000000,i=1;i<=n;i++)b[i]=sum[i];
      for(sort(b+1,b+n+1),i=1;i<=n;i++)root[i]=ins(root[i-1],1,n,lower(sum[i]));
      for(i=2;i<=n;i++)H.push(node(i,1));
      while(K--)tmp=H.top(),H.pop(),ans+=tmp.x,H.push(node(tmp.i,tmp.l,tmp.r,tmp.k+1));
      printf("%lld",ans);
      return 0;
    }
    

      

  • 相关阅读:
    Windows平台下的读写锁
    进程的阻塞和挂起的区别
    事件函数SetEvent、PulseEvent与WaitForSingleObject详解
    多线程的那点儿事(之多线程调试)
    多线程同步内功心法——PV操作上(未完待续。。。)
    读者写者问题(有bug 后续更改)
    解决VS2010控制台程序运行结束不显示请按任意键继续
    Method has too many Body parameters openfeign
    Eclipse中Cannot nest src folder解决方法
    restTemplate重定向问题 &cookie问题
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403235.html
Copyright © 2020-2023  润新知