zoukankan      html  css  js  c++  java
  • BZOJ2006: [NOI2010]超级钢琴

    2006: [NOI2010]超级钢琴

    Time Limit: 20 Sec  Memory Limit: 552 MB
    Submit: 3234  Solved: 1594
    [Submit][Status][Discuss]

    Description

    小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的
    音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级
    和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的
    所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。 
    小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。
    我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最
    大值是多少。

    Input

    第一行包含四个正整数n, k, L, R。其中n为音符的个数,k为乐曲所包含的超级和弦个数,L和R分别是超级和弦所
    包含音符个数的下限和上限。 接下来n行,每行包含一个整数Ai,表示按编号从小到大每个音符的美妙度。
    N<=500,000
    k<=500,000
    -1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲

    Output

    只有一个整数,表示乐曲美妙度的最大值。

    Sample Input

    4 3 2 3
    3
    2
    -6
    8

    Sample Output

    11

    【样例说明】
    共有5种不同的超级和弦:
    音符1 ~ 2,美妙度为3 + 2 = 5
    音符2 ~ 3,美妙度为2 + (-6) = -4
    音符3 ~ 4,美妙度为(-6) + 8 = 2
    音符1 ~ 3,美妙度为3 + 2 + (-6) = -1
    音符2 ~ 4,美妙度为2 + (-6) + 8 = 4
    最优方案为:乐曲由和弦1,和弦3,和弦5组成,美妙度为5 + 2 + 4 = 11。

    HINT


    Source

    【题解】

    初始时,对于每一个右端点,他所选的最优左端点很容易求出:前缀和+st表

    贪心选区间和最大的(堆实现)。选了某个右端点i,对应左端点pos后,

    只要i不被选,以i为右端点的区间的左端点不是pos的区间就不可能被选

    pos被选了之后

    我们不难发现

    右端点i的最优左端点在i - r + 1, pos - 1 和 pos + 1, i - l + 1里面

    取两个左端点最优值压入堆中嘛?当然不是,两个左端点都应加入堆中。

    两个端点一个能构成最大,另一个可能构成次大。

    因long long和st表的ij弄反被卡

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <queue>
      6 #include <vector>
      7 #define max(a, b) ((a) > (b) ? (a) : (b))
      8 #define min(a, b) ((a) < (b) ? (a) : (b))
      9 
     10 inline void read(long long &x)
     11 {
     12     x = 0;char ch = getchar(), c = ch;
     13     while(ch < '0' || ch > '9')c = ch, ch = getchar();
     14     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
     15     if(c == '-')x = -x;
     16 }
     17 
     18 const long long MAXN = 500000 + 10;
     19 const long long MAXK = 500000 + 10;
     20 
     21 long long n,k,l,r,num[MAXN],st[20][MAXN],rank[20][MAXN],M,pow2[30],ans;
     22 
     23 struct Node
     24 {
     25     long long value, l, r, rank, i;
     26     Node(long long _value, long long _l, long long _r, long long _rank, long long _i){value = _value, l = _l, r = _r,rank = _rank;i = _i;}    
     27     Node(){}
     28 };
     29 
     30 struct cmp
     31 {
     32     bool operator()(Node a, Node b)    
     33     {
     34         return a.value < b.value;
     35     }
     36 };
     37 
     38 std::priority_queue<Node, std::vector<Node>, cmp> q;
     39 
     40 void yuchuli()
     41 {
     42     while(pow2[M] <= n)++ M;
     43     --M;
     44     for(register long long i = 1;i <= M;++ i)
     45         for(register long long j = 0;j <= n;++ j)
     46         {
     47             if(j + pow2[i] - 1 > n)continue;
     48             if(st[i - 1][j] < st[i - 1][j + pow2[i - 1]])
     49             {
     50                 st[i][j] = st[i - 1][j];
     51                 rank[i][j] = rank[i - 1][j];
     52             }
     53             else
     54             {
     55                 st[i][j] = st[i - 1][j + pow2[i - 1]];
     56                 rank[i][j] = rank[i - 1][j + pow2[i - 1]];
     57             }
     58         }
     59 }
     60 
     61 long long find(long long l, long long r)
     62 {
     63     if(l > r)
     64     {
     65         long long tmp = l;
     66         l = r;
     67         r = tmp;
     68     }
     69     long long m = 0;
     70     while(pow2[m] <= (r - l + 1))++ m;
     71     -- m;
     72     if(st[m][l] < st[m][r - pow2[m] + 1])
     73         return rank[m][l];
     74     else
     75         return rank[m][r - pow2[m] + 1];
     76 }
     77 
     78 int main()
     79 {
     80     read(n);read(k);read(l);read(r);
     81     pow2[0] = 1;
     82     for(register long long i = 1;i <= 25;++ i)pow2[i] = (pow2[i - 1] << 1);
     83     for(register long long i = 1;i <= n;++ i)
     84     {
     85         read(num[i]);
     86         num[i] += num[i - 1];
     87         st[0][i] = num[i];
     88         rank[0][i] = i;
     89     }
     90     yuchuli();
     91     for(register long long i = l;i <= n;++ i)
     92     {
     93         long long k = find(max(0, i - r), max(i - l, 0));
     94         q.push(Node(num[i] - num[k], max(0, i - r), max(i - l, 0), k, i));
     95     }
     96     long long now = 0;
     97     register Node tmp;
     98     register long long pos;
     99     for(;now < k;++ now)
    100     {
    101         tmp = q.top(), q.pop();
    102         long long l = tmp.l, r = tmp.r;
    103         ans += tmp.value; 
    104         if(tmp.l <= tmp.rank - 1 && tmp.l >= 0)
    105         {
    106             pos = find(max(0, tmp.l), max(tmp.rank - 1, 0));
    107             q.push(Node(num[tmp.i] - num[pos], tmp.l, tmp.rank - 1, pos, tmp.i));
    108         }
    109         if(tmp.r >= tmp.rank + 1)
    110         {
    111             pos = find(max(0, tmp.rank + 1), max(tmp.r, 0));
    112             q.push(Node(num[tmp.i] - num[pos], tmp.rank +1, tmp.r, pos, tmp.i));
    113         }
    114     }
    115     printf("%lld", ans);
    116     return 0;
    117 }
    BZOJ2006
  • 相关阅读:
    linux系统安装Mysql
    makefile通用模板
    makefile常用函数
    mysqlconnector安装
    linux添加默认路由route
    .h文件与.hpp文件的区别
    ubuntu20优化开机启动
    [javascript]js原型链以及原型链继承
    webpack4.*入门笔记
    图像编程:图片大小关系
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7472654.html
Copyright © 2011-2022 走看看