A.小红的环形字符串
思路:将s
字符串扩大两倍之后,在其之中寻找有几个字串等于t
字符串。
void solve() {
string s, t;
cin >> s >> t;
s = s + s;
int c = t.size();
int n = s.size();
int cnt = 0;
for (int i = 0; i < n / 2; ++i) {
string sub = s.substr(i, c);
if (sub == t) {
cnt++;
}
}
cout << cnt << '\n';
}
B.相邻不同数字的标记
思路:(状态机)dp。
d[i][j]
表示考虑前j
个数字时,下标为j-1
的数字是否被选上(0为没有选第j-1
个数字,1为选上了第j-1
个数字),注意i=1
时的特例即可。
时间复杂度O(n)
const int N = 100010;
int a[N], dp[2][N]; //dp[i][j]表示前j个数字里,选没选前一个数字
bool st[N];
int n, m, k;
void solve() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
string c;
cin >> c;
c = "*" + c;
for (int i = 1; i <= n; ++i) {
dp[0][i] = max(dp[0][i - 1], dp[1][i - 1]);
if (c[i] != c[i - 1] && i != 1) dp[1][i] = max(dp[0][i - 1] + a[i] + a[i - 1], dp[1][i - 1]);
}
cout << max(dp[0][n], dp[1][n]) << '\n';
}
C.小红的俄罗斯方块
思路:纯模拟,找到每次要放置这个方块的位置的最高点(相对来说),分情况讨论即可。
时间复杂度 O(n)
const int N = 200010;
int n, m, k;
int h[9];
void solve() {
int type, b;
cin >> type >> b;
if (type == 0) {
int hight = max(h[b], h[b + 1]);
h[b] = hight + 3;
h[b + 1] = hight + 1;
} else if (type == 90) {
int hight;
if (h[b] > h[b + 1] && h[b] > h[b + 2]) {
hight = h[b];
h[b] = hight + 2;
h[b + 1] = hight + 2;
h[b + 2] = hight + 2;
} else if (h[b + 1] > h[b] + 1 && h[b + 1] > h[b + 2]) {
hight = h[b + 1];
h[b] = hight + 1;
h[b + 1] = hight + 1;
h[b + 2] = hight + 1;
} else if (h[b + 2] > h[b] + 1) {
hight = h[b + 2];
h[b] = hight + 1;
h[b + 1] = hight + 1;
h[b + 2] = hight + 1;
} else {
hight = h[b];
h[b] = hight + 2;
h[b + 1] = hight + 2;
h[b + 2] = hight + 2;
}
} else if (type == 180) {
int hight;
if (h[b] > h[b + 1] + 1) {
hight = h[b];
h[b] = hight + 1;
h[b + 1] = hight + 1;
} else {
hight = h[b + 1];
h[b] = hight + 3;
h[b + 1] = hight + 3;
}
} else {
int hight = max(h[b], h[b + 1]);
hight = max(hight, h[b + 2]);
h[b] = hight + 1;
h[b + 1] = hight + 1;
h[b + 2] = hight + 2;
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _;
cin >> _;
while (_--) {
solve();
}
for (int i = 1; i <= 8; ++i) {
cout << h[i] << ' ';
}
return 0;
}
D.小红打怪
思路:贪心、二分。
用结构体存下小怪和小红打的回合数、计算出小红和每一个小怪打架消耗的生命值,按照耗损生命值从小到大排序之后计算前缀和,二分找到每一个药瓶数对应的可以打过的怪物最大数量即可。
时间复杂度O(qlogn)
const int N = 100010;
struct mons {
int a, b, cnt, d;
} monster[N];
int n, h, k;
void solve() {
cin >> n >> h >> k;
for (int i = 1; i <= n; ++i) {
cin >> monster[i].a >> monster[i].b;
int t = monster[i].a % 4;
monster[i].cnt = monster[i].a / 4 * 3 + t - (t >= 2);
monster[i].d = monster[i].b * (monster[i].cnt - 1);
}
sort(monster + 1, monster + 1 + n, [](mons a, mons b) {
return a.d < b.d;
});
for (int i = 1; i <= n; ++i) {
monster[i].d = monster[i - 1].d + monster[i].d;
}
int q;
cin >> q;
while (q--) {
int x;
cin >> x;
int hh = h + k * x;
int l = 0, r = n + 1;
while (l + 1 != r) {
int mid = l + r >> 1;
if (monster[mid].d < hh) l = mid;
else r = mid;
}
cout << l << ' ';
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _ = 1;
while (_--) {
solve();
}
return 0;
}