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 }
  • 相关阅读:
    VC字符串输出对齐问题(转)
    木马免杀全攻略(转)
    Windows Vista自动重启问题解决方法(转)
    图说VSS 6.0构架版本控制系统解决方案(转)
    几个有用的链接
    X64 Windows 2003 及XP 语言包官方下载
    .NET 3.5的版本问题(转)
    设计模式读书笔记工厂方法模式
    设计模式读书笔记装饰者模式
    设计模式读书笔记简单工厂模式
  • 原文地址:https://www.cnblogs.com/myx12345/p/9284143.html
Copyright © 2011-2022 走看看