Hello 2023 A-D

比赛链接

A

题意

给一个字符串每个物品对应的灯的照明方向,L/R 能照亮它左侧/右侧的所有物品(不包括自己对应的物品),现在能交换相邻两个灯一次(不改变照明方向),问能否找亮所有物品。

题解

知识点:贪心。

显然,如果存在 LRRL 就可以照亮全部,否则全是 LR 就不可行。

时间复杂度 O(n)

空间复杂度 O(n)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool solve() {
int n;
cin >> n;
string s;
cin >> s;
s = "?" + s;
for (int i = 1;i < n;i++) {
if (s[i] != s[i + 1]) {
if (s[i] == 'L') cout << i << '\n';
else cout << 0 << '\n';
return true;
}
}
return false;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

B

题意

构造一组数,使得任意相邻两项之和等于全部和。

题解

知识点:构造。

n 为偶数时,构造 1,1,1,1, 即可。

n 为奇数时,显然奇数项和偶数项要各自相等,随后由 a1++an=an1+an 可以得到 (n1)a1+(n3)a2=0 ,取 a1=n3,a2=1n 即可,只有 n=3 时无解(因为 a1=0)。

时间复杂度 O(n)

空间复杂度 O(n)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool solve() {
int n;
cin >> n;
if (n & 1) {
if (n == 3) return false;
cout << "YES" << '\n';
for (int i = 1;i <= n;i++) {
if (i & 1) cout << n - 3 << ' ';
else cout << 1 - n << ' ';
}
cout << '\n';
}
else {
cout << "YES" << '\n';
for (int i = 1;i <= n;i++) {
if (i & 1) cout << 1 << ' ';
else cout << -1 << ' ';
}
cout << '\n';
}
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << "NO" << '\n';
}
return 0;
}

C

题意

给一组数,可以修改元素变成其相反数。问最少修改几次,可以使得第 m 个前缀和 a1++am 是所有前缀和里最小的。

题解

知识点:枚举,前缀和,数学,贪心。

定义 a[l,r]=al++ar

k[1,m1]

a[1,k]a[1,m]a[1,k]a[1,k]+a[k+1,m]0a[k+1,m]

k[m+1,n]

a[1,k]a[1,m]a[1,m]+a[m+1,k]a[1,m]a[m+1,k]0

所以只要保证任意 i[2,m] ,满足 a[i,m]0 ;任意 i[m+1,n] ,满足 a[m+1,i]0 即可。

每次操作时,贪心地取最优的即可。

时间复杂度 O(nlogn)

空间复杂度 O(n)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[200007];
bool solve() {
int n, m;
cin >> n >> m;
for (int i = 1;i <= n;i++) cin >> a[i];
int cnt = 0;
multiset<int> ms;
ll sum = 0;
for (int i = m;i >= 2;i--) {
sum += a[i];
ms.insert(a[i]);
if (sum > 0) {
sum -= 2 * (*prev(ms.end()));
ms.erase(prev(ms.end()));
cnt++;
}
}
ms.clear();
sum = 0;
for (int i = m + 1;i <= n;i++) {
sum += a[i];
ms.insert(a[i]);
if (sum < 0) {
sum -= 2 * (*ms.begin());
ms.erase(ms.begin());
cnt++;
}
}
cout << cnt << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

D

题意

给定一组头发长度 ai ,以及理想头发长度 bi

理发师有刀片 xi ,每个刀片只能用一次,每次可以修减一段连续区间的头发,满足 ai=min(ai,x),i[L,R]

问理发师能不能通过这些刀片将 a 修剪至 b

题解

知识点:单调栈。

显然 ai<bi 无解。

利用最大值单调栈维护刀片的值。以下按顺序满足:

  1. bi 大于栈顶刀片,则栈顶刀片因为太小不能再用了,刀片需要出栈直至 bi 小于等于栈顶刀片或栈空。
  2. bi=ai ,说明 bi 不需要修剪,什么都不用干。
  3. biai ,说明 bi 需要修剪,此时如果 bi 小于栈顶刀片或栈空,则需要使用新的刀片,满足 x=b[i] ,如果不存在这个刀片则无解。

全部满足后,即 YES

时间复杂度 O(n+mlogm)

空间复杂度 O(n+m)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[200007];
int b[200007];
bool solve() {
int n;
cin >> n;
for (int i = 1;i <= n;i++) cin >> a[i];
for (int i = 1;i <= n;i++) cin >> b[i];
int m;
cin >> m;
map<int, int> mp;
for (int i = 1;i <= m;i++) {
int x;
cin >> x;
mp[x]++;
}
stack<int> st;
for (int i = 1;i <= n;i++) {
if (a[i] < b[i]) return false;
while (!st.empty() && b[i] > st.top()) st.pop();
if (a[i] != b[i]) {
if (st.empty() || b[i] < st.top()) {
if (mp[b[i]]) {
mp[b[i]]--;
st.push(b[i]);
}
else return false;
}
}
}
cout << "YES" << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << "NO" << '\n';
}
return 0;
}
posted @   空白菌  阅读(184)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示