k-Amazing Numbers (CodeForces - 1416A )
题意
给出一个数组,依次求该数组中所有长度为k(1<=k<=n)的子段,若这些子段中存在相同的数,则输出这些相同的数中的最小值,否则输出-1
思路
首先将数组中所有相同的数提出来,然后对于每一种相同的数 i,计算它们之间的间隔,取最大间隔mx,表示 i 是所有长度为mx的所有子段的一个共有数,用一个ans数组存储所有长度为k的子段的共有值的最小值
然后对于任意一个长为x的子段的共有最小值,都可以由比长为y(y<x)的子段的共有最小值来更新
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5, INF = 0x3f3f3f3f;
int ans[N];
vector<int> v[N];
void solve() {
int n;
scanf("%d", &n);
for (int i = 0; i <= n + 1; i++) {
v[i].clear();
ans[i] = INF;
}
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
v[x].push_back(i);
}
for (int i = 1; i <= n; i++) {
if (v[i].size()) {
int mx = 0;
for (int j = 1; j < v[i].size(); j++)
mx = max(mx, v[i][j] - v[i][j - 1]);
mx = max(mx, v[i].front());
mx = max(mx, n - v[i].back() + 1);
ans[mx] = min(ans[mx], i);
}
}
for (int i = 2; i <= n; i++)
ans[i] = min(ans[i], ans[i - 1]);
for (int i = 1; i <= n; i++) {
if (ans[i] < INF)
printf("%d ", ans[i]);
else
printf("-1 ");
}
puts("");
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
Mortal Kombat Tower (CodeForces - 1418C )
题意
给出一个数组,数组中值为1代表boss,值为0代表小怪,你和你的朋友一起打怪,你的朋友每击败一只boss需要耗费1点体力,击败小怪不用,而你击败boss或小怪都不耗费体力,每人每次必须选择击败当前最靠前的1只或2只怪物,你的朋友先手,求击败所有怪物你的朋友至少需要耗费的体力
思路
看dalao用的dp,看着不是很懂,等学明白了再回来补题解
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int a[N], f[N][2];
void solve() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
memset(f, 0x3f, sizeof f);
f[1][0] = a[1];
f[2][0] = f[1][0] + a[2];
f[2][1] = f[1][0];
for (int i = 3; i <= n; i++) {
f[i][0] = min(f[i - 1][1] + a[i], f[i - 2][1] + a[i - 1] + a[i]);
f[i][1] = min(f[i - 1][0], f[i - 2][0]);
}
printf("%d\n", min(f[n][0], f[n][1]));
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}