题目链接
CodeForce 1706B. Making Towers
不太会做贪心的题目。
思路
记两个相邻的同色色块,之间所夹的色块数量 k k k,容易看出,
- 当 k k k为偶数,我们可以向左铺 k / 2 k/2 k/2块,再向右铺 k / 2 k/2 k/2块。此时tower的高度可以+1
- 对于
k
k
k为奇数的情况,可以向左(或向右)铺
(
k
+
1
)
/
2
(k + 1)/2
(k+1)/2块。此时我们可以:
- 在当前位置重新建一个新tower
- 或消费掉当前色块,从而继续向左铺当前颜色,从而使得后续的色块又能与先前的tower连接起来,使得其能够更大。
如果在上面所夹奇数色块的情况发生时,我们已建立出的tower高度为
h
1
h_1
h1,而从当前位置能够建立的新tower的高度
h
2
h_2
h2
那么
a
n
s
=
max
(
h
2
−
1
+
h
1
,
h
1
,
h
2
)
ans=\max(h_2 - 1 + h_1, h_1,h_2)
ans=max(h2−1+h1,h1,h2)
而
h
1
≥
1
,
h
2
≥
1
h_1\ge1,h_2 \ge 1
h1≥1,h2≥1,故
h
2
−
1
+
h
1
≥
h
1
,
h
2
h_2-1+h_1 \ge h_1, h_2
h2−1+h1≥h1,h2
可见后两种情况都被涵盖在第一种情况之中,那么我们只需要尽可能让之前的塔更高就行了。
综上,我们只需要统计相邻色块之间是否相夹偶数块色块的数量,即为
a
n
s
ans
ans
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main() {
int n_case;
cin >> n_case;
while (n_case--) {
int n;
cin >> n;
vector<vector<int>> c(n + 1);
for (int i = 0; i < n; ++i) {
int color;
cin >> color;
c[color].push_back(i);
}
for (int i = 1; i <= n; ++i) {
auto &g = c[i];
int len = g.size();
LL ans = 1;
if (len > 1) {
for (int j = 1; j < len; ++j)
if ((g[j] - g[j - 1] - 1) % 2 == 0)
++ans;
} else
ans = len;
printf("%lld", ans);
if (i != n)
printf(" ");
}
printf("\n");
}
}