BZOJ2006: [NOI2010]超级钢琴
Posted 嘒彼小星
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2006: [NOI2010]超级钢琴相关的知识,希望对你有一定的参考价值。
2006: [NOI2010]超级钢琴
Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 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
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。
【样例说明】
共有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: [NOI2010]超级钢琴的主要内容,如果未能解决你的问题,请参考以下文章