zoukankan      html  css  js  c++  java
  • 【BZOJ2006】超级钢琴(RMQ,priority_queue)

    题意:

    思路:

    用三元组(i, l, r)表示右端点为i,左端点在[l, r]之间和最大的区间([l, r]保证是对于i可行右端点区间的一个子区间),我们用堆维护一些这样的三元组。

    堆中初始的元素为每个i,并且[l, r]为这个i可行左端点的区间。

    假如某次最大值为(i, l, r),并且j为那个和最大区间的左端点,那么需要往堆中加入两个三元组(i, l, j-1)和(i, j+1, r)。

    对于一个三元组,计算对应最大和的问题实际就是一个RMQ问题,可以通过Sparse Table在O(NlogN) – O(1)的时间内解决。

    实际上固定左端点的方法也类似,程序中使用这种方法

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<queue>
     6 #include<iostream>
     7 #include<algorithm>
     8 #include<set>
     9 #include<map>
    10 #define mp(a,b,c,d) (data){a,b,c,d}
    11 #define inf 1000000000
    12 #define ll long long
    13 #define MAXN 510000
    14 using namespace std;
    15 struct data{int i,l,r,t;};
    16 
    17 int f[MAXN][20];
    18 int a[MAXN];
    19 
    20 int query(int x,int y)
    21 {
    22     if(x>y) return 0;
    23     int len=y-x+1; int l=log(len)/log(2);
    24     int s1=f[x][l];
    25     int s2=f[y-(1<<l)+1][l];
    26     if(a[s1]>a[s2]) return s1;
    27      else return s2;
    28 }
    29 
    30 bool operator<(data x,data y)
    31 {
    32     return a[x.t]-a[x.i-1]<a[y.t]-a[y.i-1];
    33 }
    34 
    35 int main()
    36 {
    37     freopen("bzoj2006.in","r",stdin);
    38     freopen("bzoj2006.out","w",stdout);
    39     priority_queue<data,vector<data> >q;
    40     int n,K,L,R;
    41     scanf("%d%d%d%d",&n,&K,&L,&R);
    42     for(int i=1;i<=n;i++) 
    43     {
    44         scanf("%d",&a[i]);
    45         a[i]+=a[i-1];
    46         f[i][0]=i;
    47     }
    48     int l=log(n)/log(2);
    49     for(int i=1;i<=l;i++)
    50      for(int j=1;j+(1<<i)-1<=n;j++) 
    51      {
    52          int x=f[j][i-1]; int y=f[j+(1<<(i-1))][i-1];
    53          if(a[x]>a[y]) f[j][i]=x;
    54           else f[j][i]=y;
    55      }
    56     for(int i=1;i<=n;i++)
    57      if(i+L-1<=n)
    58      {
    59          int t=min(n,i+R-1);
    60          q.push(mp(i,i+L-1,t,query(i+L-1,t)));
    61      }
    62     ll ans=0;
    63     for(int i=1;i<=K;i++)
    64     {
    65         data t=q.top();q.pop();
    66         ans+=a[t.t]-a[t.i-1];
    67         //printf("%lld
    ",ans);
    68         if(t.t-1>=t.l) q.push(mp(t.i,t.l,t.t-1,query(t.l,t.t-1)));
    69         if(t.t+1<=t.r) q.push(mp(t.i,t.t+1,t.r,query(t.t+1,t.r)));
    70     }
    71     printf("%lld
    ",ans);
    72     return 0;
    73 }
  • 相关阅读:
    hihocoder 1049 后序遍历
    hihocoder 1310 岛屿
    Leetcode 63. Unique Paths II
    Leetcode 62. Unique Paths
    Leetcode 70. Climbing Stairs
    poj 3544 Journey with Pigs
    Leetcode 338. Counting Bits
    Leetcode 136. Single Number
    Leetcode 342. Power of Four
    Leetcode 299. Bulls and Cows
  • 原文地址:https://www.cnblogs.com/myx12345/p/9284143.html
Copyright © 2011-2022 走看看