zoukankan      html  css  js  c++  java
  • 洛谷 P2048 [NOI2010]超级钢琴(优先队列,RMQ)

    传送门

    我们定义$(p,l,r)=max{sum[t]-sum[p-1],p+l-1leq tleq p+r-1 }$

    那么因为对每一个$p$来说$sum[p-1]$是一个定值,所以我们只要在$[p+l-1,p+r-1]$的区间里找出最大的$sum[t]$就行了,这就是一个RMQ问题,开个ST表就行了

    一开始我们用优先队列存储所有的$(p,l,r)$,然后每一次取出队首更新答案

    注意如果$t$被选了,答案还有可能在$t$两边的区间里,所以记得把$(p,l,t-1)$和$(p,t+1,r)$给扔进优先队列里

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<cmath>
     8 #define ll long long
     9 using namespace std;
    10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    11 char buf[1<<21],*p1=buf,*p2=buf;
    12 inline int read(){
    13     #define num ch-'0'
    14     char ch;bool flag=0;int res;
    15     while(!isdigit(ch=getc()))
    16     (ch=='-')&&(flag=true);
    17     for(res=num;isdigit(ch=getc());res=res*10+num);
    18     (flag)&&(res=-res);
    19     #undef num
    20     return res;
    21 }
    22 const int N=500005,LOG=20;
    23 ll sum[N],st[N][LOG];
    24 int n,k,l,r;
    25 void init(){
    26     for(int i=1;i<=n;++i) st[i][0]=i;
    27     for(int j=1;(1<<j)<=n;++j)
    28     for(int i=1;i+(1<<j)-1<=n;++i){
    29         int x=st[i][j-1],y=st[i+(1<<j-1)][j-1];
    30         st[i][j]=sum[x]>sum[y]?x:y;
    31     }
    32 }
    33 inline int query(int l,int r){
    34     int k=log2(r-l+1);
    35     int x=st[l][k],y=st[r-(1<<k)+1][k];
    36     return sum[x]>sum[y]?x:y;
    37 }
    38 struct node{
    39     int p,l,r,t;
    40     node(){}
    41     node(int p,int l,int r):p(p),l(l),r(r),t(query(l,r)){}
    42     inline bool operator <(const node &b)const
    43     {return sum[t]-sum[p-1]<sum[b.t]-sum[b.p-1];}
    44 };
    45 priority_queue<node> q;
    46 int main(){
    47 //    freopen("testdata.in","r",stdin);
    48     n=read(),k=read(),l=read(),r=read();
    49     for(int i=1;i<=n;++i)
    50     sum[i]=read(),sum[i]+=sum[i-1];
    51     init();
    52     for(int i=1;i<=n;++i)
    53     if(i+l-1<=n)
    54     q.push(node(i,i+l-1,min(i+r-1,n)));
    55     ll ans=0;
    56     while(k--){
    57         int p=q.top().p,l=q.top().l,r=q.top().r,t=q.top().t;
    58         q.pop();
    59         ans+=sum[t]-sum[p-1];
    60         if(l!=t) q.push(node(p,l,t-1));
    61         if(t!=r) q.push(node(p,t+1,r));
    62     }
    63     printf("%lld
    ",ans);
    64     return 0;
    65 }
  • 相关阅读:
    每日一练leetcode
    每日一练leetcode
    每日一练 leetcode
    每日一练leetcode
    每日一练leetcode
    leetcode每日一练
    BigDecimal类 定义及用法
    每日一练leetcode
    每日一练leetcode
    字符串表达式校验&求值(C#实现) 附代码
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9676536.html
Copyright © 2011-2022 走看看