zoukankan      html  css  js  c++  java
  • luogu2048 [NOI2010]超级钢琴 (优先队列+主席树)

    思路:先扫一遍所有点作为右端点的情况,把它们能产生的最大值加到一个优先队列里,然后每次从优先队列里取出最大值,再把它对应的区间的次大值加到优先队列里,这样做K次

    可以用一个前缀和,每次找i为右端点的第K大时,就相当于找[i-R,i-L](可能有±2的偏差,会意)的第K小值,然后把它减掉

    这个可以用主席树来做

    为了做起来方便,下标从2开始;离散化的话会稍微快一点

    这个第K大也可以不用主席树来维护,而是每次找到那个最小值以后把这个区间从那个点拆成两部分,再把这两部分加到优先队列里

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define CLR(a,x) memset(a,x,sizeof(a))
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn=5e5+10,logn=20,inf=5e5+1;
     7 
     8 inline ll rd(){
     9     ll x=0;char c=getchar();int neg=1;
    10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 int N,K,L,R;
    16 int sum[maxn],tmp[maxn];
    17 int rot[maxn],pct,cnt[maxn*logn],ch[maxn*logn][2];
    18 int tim[maxn],ori[maxn];
    19 priority_queue<pa > q;
    20 
    21 void insert(int pre,int &p,int l,int r,int x){
    22     p=++pct;cnt[p]=cnt[pre]+1;
    23     if(l<r){
    24         int m=l+r>>1;
    25         if(x<=m) ch[p][1]=ch[pre][1],insert(ch[pre][0],ch[p][0],l,m,x);
    26         else ch[p][0]=ch[pre][0],insert(ch[pre][1],ch[p][1],m+1,r,x);
    27     }
    28 }
    29 int query(int pre,int p,int l,int r,int k){
    30     if(k>cnt[p]-cnt[pre]) return -inf;
    31     if(l==r) return l;
    32     int w=cnt[ch[p][0]]-cnt[ch[pre][0]],m=l+r>>1;
    33     if(k<=w) return query(ch[pre][0],ch[p][0],l,m,k);
    34     else return query(ch[pre][1],ch[p][1],m+1,r,k-w);
    35 }
    36 
    37 int main(){
    38     //freopen("","r",stdin);
    39     int i,j,k;
    40     N=rd(),K=rd();L=rd(),R=rd();
    41     for(i=2;i<=N+1;i++) tmp[i]=sum[i]=sum[i-1]+rd();
    42     sort(tmp+1,tmp+N+2);int mm=unique(tmp+1,tmp+N+2)-tmp-1;
    43     for(i=1;i<=N+1;i++){
    44         int x=lower_bound(tmp+1,tmp+mm+1,sum[i])-tmp;
    45         ori[x]=sum[i];sum[i]=x;
    46         // printf("%d %d
    ",ori[x],sum[i]);
    47     }
    48     for(i=1;i<=N+1;i++){
    49         insert(rot[i-1],rot[i],0,inf,sum[i]);
    50         // printf("%d
    ",cnt[rot[i]]);
    51     }
    52     ll ans=0;
    53     for(i=L+1;i<=N+1;i++){
    54         int x=query(rot[max(i-R-1,0)],rot[i-L],0,inf,tim[i]=1);
    55         
    56         q.push(make_pair(ori[sum[i]]-ori[x],i));
    57     }
    58     for(i=1;i<=K;i++){
    59         int p=q.top().second;ans+=q.top().first;
    60         // printf("%d %d
    ",p,ans);
    61         q.pop();tim[p]++;
    62         int x=query(rot[max(p-R-1,0)],rot[p-L],0,inf,tim[p]);
    63         if(x==-inf) continue;
    64         // printf("%d %d %d
    ",p,tim[p],x);
    65         q.push(make_pair(ori[sum[p]]-ori[x],p));
    66     }
    67     printf("%lld
    ",ans);
    68     return 0;
    69 }
  • 相关阅读:
    Team Foundation Sidekicks 2010
    Asp.net页面传值的方式汇总
    轻量级IOC框架Ninject使用
    AutoMapper使用简单总结
    页面请求的方式(Get与Post)
    总结2012 规划2013
    在reset css后两个input之间还是出现默认间隔的问题。
    js学习笔记事件委托
    程序猿工具——svn
    JS 事件添加onclick写法注意。
  • 原文地址:https://www.cnblogs.com/Ressed/p/9758708.html
Copyright © 2011-2022 走看看