小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的
音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级
和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的
所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。
小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。
我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最
大值是多少。
第一行包含四个正整数n, k, L, R。其中n为音符的个数,k为乐曲所包含的超级和弦个数,L和R分别是超级和弦所
包含音符个数的下限和上限。 接下来n行,每行包含一个整数Ai,表示按编号从小到大每个音符的美妙度。
N<=500,000
k<=500,000
-1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲
1 #include <queue>
2 #include <cstdio>
3
4 inline int nextChar(void)
5 {
6 const static int siz = 1024;
7
8 static char buf[siz];
9 static char *hd = buf + siz;
10 static char *tl = buf + siz;
11
12 if (hd == tl)
13 fread(hd = buf, 1, siz, stdin);
14
15 return *hd++;
16 }
17
18 inline int nextInt(void)
19 {
20 register int ret = 0;
21 register int neg = false;
22 register int bit = nextChar();
23
24 for (; bit < 48; bit = nextChar())
25 if (bit == ‘-‘)neg ^= true;
26
27 for (; bit > 47; bit = nextChar())
28 ret = ret * 10 + bit - 48;
29
30 return neg ? -ret : ret;
31 }
32
33 const int siz = 500005;
34
35 int N, M, L, R;
36
37 int num[siz];
38 int sum[siz];
39
40 int st[siz][25], log[siz];
41
42 inline void preworkRMQ(void)
43 {
44 for (int i = 1; i <= N; ++i)
45 st[i][0] = i;
46
47 for (int i = 1; (1 << i) <= N; ++i)
48 for (int j = 1; j + (1 << i) - 1 <= N; ++j)
49 {
50 int x = st[j][i - 1];
51 int y = st[j + (1 << (i - 1))][i - 1];
52 st[j][i] = sum[x] > sum[y] ? x : y;
53 }
54
55 log[0] = -1;
56
57 for (int i = 1; i <= N; ++i)
58 log[i] = log[i >> 1] + 1;
59 }
60
61 inline int query(int l, int r)
62 {
63 if (l == r)
64 return l;
65
66 int t = log[r - l + 1];
67
68 int x = st[l][t];
69 int y = st[r - (1 << t) + 1][t];
70
71 return sum[x] > sum[y] ? x : y;
72 }
73
74 struct data
75 {
76 int p, t, l, r;
77
78 data(void) {};
79 data(int a, int b, int c, int d) :
80 p(a), t(b), l(c), r(d) {};
81 };
82
83 inline bool operator < (const data &a, const data &b)
84 {
85 return sum[a.t] - sum[a.p - 1] < sum[b.t] - sum[b.p - 1];
86 }
87
88 std::priority_queue<data> h;
89
90 signed main(void)
91 {
92 N = nextInt();
93 M = nextInt();
94 L = nextInt();
95 R = nextInt();
96
97 for (int i = 1; i <= N; ++i)
98 num[i] = nextInt();
99
100 for (int i = 1; i <= N; ++i)
101 sum[i] = sum[i - 1] + num[i];
102
103 preworkRMQ();
104
105 long long ans = 0;
106
107 for (int i = 1; i <= N - L + 1; ++i)
108 {
109 int l = i + L - 1;
110 int r = i + R - 1;
111
112 if (r > N)
113 r = N;
114
115 h.push(data(i, query(l, r), l, r));
116 }
117
118 for (int i = 1; i <= M; ++i)
119 {
120 data top = h.top(); h.pop();
121
122 ans += sum[top.t] - sum[top.p - 1];
123
124 if (top.t > top.l)
125 h.push(data(top.p, query(top.l, top.t - 1), top.l, top.t - 1));
126 if (top.t < top.r)
127 h.push(data(top.p, query(top.t + 1, top.r), top.t + 1, top.r));
128 }
129
130 printf("%lld\n", ans);
131 }