Atcoder Beginner Contest 395记录
AtCoder Beginner Contest 395记录
A - Strictly Increasing?
模拟
思路
直接遍历一遍就行
代码
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
int nums[110];
void solve()
{
int n = 0;
std::cin >> n;
for (int i = 1; i <= n; i++) std::cin >> nums[i];
for (int i = 1; i < n; i++)
{
if (nums[i] >= nums[i + 1])
{
std::cout << "No" << endl;
return;
}
}
std::cout << "Yes" << endl;
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); std::cout.tie(nullptr);
//freopen("out.txt", "w", stdout);
int t = 1;
//std::cin >> t;
while(t--)
{
solve();
}
return 0;
}
B - Make Target
模拟
思路
找到规律直接模拟
要涂色的图形是左上和右下坐标分别为
代码
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
char mat[55][55];
void solve()
{
memset(mat, '.', sizeof(mat));
int n = 0;
std::cin >> n;
for (int i = 1; i <= (n + 1) / 2; i += 2)
{
for (int j = i; j <= n + 1 - i; j++)
{
mat[i][j] = '#';
mat[j][i] = '#';
mat[n + 1 - i][j] = '#';
mat[j][n + 1 - i] = '#';
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
std::cout << mat[i][j];
}
std::cout << endl;
}
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); std::cout.tie(nullptr);
//freopen("out.txt", "w", stdout);
int t = 1;
//std::cin >> t;
while(t--)
{
solve();
}
return 0;
}
C - Shortest Duplicate Subarray
思维
思路
可以记录每一个数上次出现的位置,这个数再次出现时就更新答案
也可以使用滑动窗口,这里用的滑动窗口,有些麻烦了
代码
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
int nums[200010];
std::deque<int> q;
int cnt[1000010];
void solve()
{
int n = 0;
std::cin >> n;
for (int i = 1; i <= n; i++)
{
std::cin >> nums[i];
}
int ans = 1e12;
for (int i = 1; i <= n; i++)
{
if(q.empty())
{
cnt[nums[i]]++;
q.push_back(nums[i]);
continue;
}
q.push_back(nums[i]);
cnt[nums[i]]++;
if (cnt[nums[i]] == 2)
{
while(cnt[nums[i]] == 2)
{
int t = q.front();
q.pop_front();
cnt[t]--;
}
ans = std::min(ans, (int)q.size() + 1);
}
}
if (ans == 1e12)
{
std::cout << -1 << endl;
}
else
{
std::cout << ans << endl;
}
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); std::cout.tie(nullptr);
//freopen("out.txt", "w", stdout);
int t = 1;
//std::cin >> t;
while(t--)
{
solve();
}
return 0;
}
D - Pigeon Swap
思维
思路
不要看错问题,操作2是把
鸽巢的位置是变化的,但是交换鸽巢的时候鸽子的位置不变化,可以维护鸽子在哪个位置,鸽巢在哪个位置,每个位置上放的是哪一个鸽巢
代码
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 1e6 + 5;
const int inf = 0x7f7f7f7f;
int faz[maxn]; // faz[i]鸽子i在哪一个位置
int pos[maxn]; // pos[i]笼子i在哪一个位置
int mp[maxn]; // mp[i]位置i是哪一个笼子
void solve()
{
int n = 0, q = 0;
std::cin >> n >> q;
for (int i = 1; i <= n; i++)
{
faz[i] = i;
pos[i] = i;
mp[i] = i;
}
int k = 0, a = 0, b = 0;
for (int i = 1; i <= q; i++)
{
std::cin >> k;
if(k == 1)
{
std::cin >> a >> b;
faz[a] = pos[b];
}
else if (k == 2)
{
std::cin >> a >> b;
int t1 = pos[a], t2 = pos[b];
pos[a] = t2;
pos[b] = t1;
mp[t1] = b;
mp[t2] = a;
}
else
{
std::cin >> a;
std::cout << mp[faz[a]] << endl;
}
}
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); std::cout.tie(nullptr);
//freopen("out.txt", "w", stdout);
int t = 1;
//std::cin >> t;
while(t--)
{
solve();
}
return 0;
}
E - Flip Edge
最短路,动态规划,思维
思路
有点类似于分层图?
多了一种可以反转边的操作,那么在使用
因为有反转状态,所以存图的时候反边也要存下来,但是要记录状态,这里为了方便可以用链式前向星存图
struct Edge
{
int u, v, st, nxt;
}edge[maxn << 1];
st为0时说明这条边是反转之前的边,st为1时说明这条边是反转之后的边
状态转移:
当走边
if (edge[i].st == 0)
{
if(dp[tt][0] > dp[t][0] + 1)
{
dp[tt][0] = dp[t][0] + 1;
q.push({tt, dp[tt][0], 0});
}
if (dp[tt][0] > dp[t][1] + x + 1)
{
dp[tt][0] = dp[t][1] + x + 1;
q.push({tt, dp[tt][0], 0});
}
}
else
{
if (dp[tt][1] > dp[t][1] + 1)
{
dp[tt][1] = dp[t][1] + 1;
q.push({tt, dp[tt][1], 1});
}
if (dp[tt][1] > dp[t][0] + x + 1)
{
dp[tt][1] = dp[t][0] + x + 1;
q.push({tt, dp[tt][1], 1});
}
}
代码
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
int cnt = 0;
int head[maxn];
int vis[maxn][2];
int dp[maxn][2]; // dp[i][1/0] 到达顶点i当前状态是/否反转的最小花费
struct Edge
{
int u, v, st, nxt;
}edge[maxn << 1];
struct Node
{
int to, w, st;
bool operator < (const Node &t) const
{
return w > t.w;
}
};
std::priority_queue<Node> q;
void AddEdge(int u, int v, int st)
{
edge[++cnt].u = u;
edge[cnt].v = v;
edge[cnt].st = st;
edge[cnt].nxt = head[u];
head[u] = cnt;
}
int n = 0, m = 0, x = 0;
void dij()
{
q.push({1, 0, 0});
dp[1][0] = 0;
while(!q.empty())
{
Node tmp = q.top();
q.pop();
if (vis[tmp.to][tmp.st]) continue;
vis[tmp.to][tmp.st] = 1;
int t = tmp.to;
for (int i = head[t]; i != -1; i = edge[i].nxt)
{
int tt = edge[i].v;
if (edge[i].st == 0)
{
if(dp[tt][0] > dp[t][0] + 1)
{
dp[tt][0] = dp[t][0] + 1;
q.push({tt, dp[tt][0], 0});
}
if (dp[tt][0] > dp[t][1] + x + 1)
{
dp[tt][0] = dp[t][1] + x + 1;
q.push({tt, dp[tt][0], 0});
}
}
else
{
if (dp[tt][1] > dp[t][1] + 1)
{
dp[tt][1] = dp[t][1] + 1;
q.push({tt, dp[tt][1], 1});
}
if (dp[tt][1] > dp[t][0] + x + 1)
{
dp[tt][1] = dp[t][0] + x + 1;
q.push({tt, dp[tt][1], 1});
}
}
}
}
}
void solve()
{
std::cin >> n >> m >> x;
for (int i = 1; i <= n; i++)
{
head[i] = -1;
dp[i][0] = dp[i][1] = 1e18;
}
int u, v;
for (int i = 1; i <= m; i++)
{
std::cin >> u >> v;
AddEdge(u, v, 0);
AddEdge(v, u, 1);
}
dij();
std::cout << std::min(dp[n][0], dp[n][1]);
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); std::cout.tie(nullptr);
//freopen("out.txt", "w", stdout);
int t = 1;
//std::cin >> t;
while(t--)
{
solve();
}
return 0;
}
F - Smooth Occlusion
思路
花费最多的情况就是
如果找到一个合法的
那么如何
当
对于第一个牙齿区间就是
对于第
然后判断区间合不合法就好了:区间左端点<=区间右端点
代码
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
struct custom_hash
{
static uint64_t splitmix64(uint64_t x)
{
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return x;
}
size_t operator () (uint64_t x) const
{
static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); // 时间戳
return splitmix64(x + FIXED_RANDOM);
}
};
int u[maxn], d[maxn];
int n = 0, x = 0;
bool check(int h)
{
int mn = std::max(h - d[1], 0ll);
int mx = std::min(u[1], h);
if (mx < mn) return false;
for (int i = 2; i <= n; i++)
{
int tle = std::max(h - d[i], 0ll);
int tri = std::min(u[i], h);
int tmn = std::max(tle, mn - x);
int tmx = std::min(tri, mx + x);
if (tmx < tmn) return false;
mn = tmn, mx = tmx;
}
return true;
}
void solve()
{
std::cin >> n >> x;
int s = 1e18, sum = 0;
for (int i = 1; i <= n; i++)
{
std::cin >> u[i] >> d[i];
s = std::min(s, u[i] + d[i]);
sum += u[i] + d[i];
}
int l = -1, r = s + 1;
while(l + 1 < r)
{
int h = (l + r) >> 1;
if(check(h))
{
l = h;
}
else
{
r = h;
}
}
std::cout << sum - l * n << endl;
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); std::cout.tie(nullptr);
//freopen("out.txt", "w", stdout);
int t = 1;
//std::cin >> t;
while(t--)
{
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现