Toyota Programming Contest 2024#2(AtCoder Beginner Contest 341)
A - Print 341
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
void solve()
{
int n;
cin >> n;
int cur = 1;
for (int i = 1; i <= 2 * n + 1; i++)
{
cout << cur;
cur ^= 1;
}
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
B - Foreign Exchange
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
void solve()
{
ll n;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
vector<ll> s(n + 1), t(n + 1);
for (int i = 1; i < n; i++)
{
cin >> s[i] >> t[i];
ll k = a[i] / s[i];
a[i + 1] += k * t[i];
}
cout << a[n] << endl;
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
C - Takahashi Gets Lost
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
void solve()
{
int n, m, l;
cin >> n >> m >> l;
string s;
cin >> s;
vector<string> g(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> g[i];
g[i] = ' ' + g[i];
}
auto bfs = [&](int a, int b) -> bool
{
for (auto c : s)
{
if (c == 'L')
{
b--;
}
else if (c == 'R')
{
b++;
}
else if (c == 'U')
{
a--;
}
else
{
a++;
}
if (g[a][b] != '.' || a < 1 || b < 1 || a > n || b > m)
{
return false;
}
}
return true;
};
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (g[i][j] == '.')
{
if (bfs(i, j))
{
cnt++;
}
}
}
}
cout << cnt << endl;
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
D - Only one of two
解题思路:
假设答案为\(x\)。
那么\(x\)内\(a的倍数 + b的倍数 - ab的倍数= k\)。如果\(x\)变大,\(a的倍数 + b的倍数 - ab的倍数 \geq k\),反之,小于等于。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
ll gcd(ll a, ll b)
{
return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b)
{
return a * b / gcd(a, b);
}
void solve()
{
ll a, b, k;
cin >> a >> b >> k;
ll l = -1;
ll r = 1e18;
auto check = [&](ll mid)
{
ll c1 = mid / a;
ll c2 = mid / b;
ll c3 = mid / lcm(a, b);
return (c1 + c2 - 2 * c3 >= k);
};
while (l + 1 < r)
{
ll mid = l + r >> 1;
if (check(mid))
{
r = mid;
}
else
{
l = mid;
}
}
cout << r << endl;
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
E - Alternating String
解题思路:
维护区间端点,区间修改,区间查询,可用线段树。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const int N = 5e5 + 10;
bool tr[N * 4];
int lc[N * 4];
int rc[N * 4];
int laz[N * 4];
int n, q;
string s;
void pushup(int u)
{
lc[u] = lc[u << 1];
rc[u] = rc[u << 1 | 1];
if (rc[u << 1] == lc[u << 1 | 1])
{
tr[u] = false;
}
else
{
tr[u] = true;
}
if (tr[u << 1] == false || tr[u << 1 | 1] == false)
{
tr[u] = false;
}
}
void pushdown(int u, int l, int r)
{
if (laz[u])
{
lc[u << 1] ^= laz[u];
rc[u << 1] ^= laz[u];
lc[u << 1 | 1] ^= laz[u];
rc[u << 1 | 1] ^= laz[u];
laz[u << 1] ^= laz[u];
laz[u << 1 | 1] ^= laz[u];
laz[u] = 0;
}
}
void build(int u, int l, int r)
{
if (l == r)
{
tr[u] = true;
rc[u] = lc[u] = s[l] - '0';
laz[u] = 0;
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int l, int r, int nl, int nr)
{
if (l >= nl && r <= nr)
{
lc[u] ^= 1;
rc[u] ^= 1;
laz[u] ^= 1;
return;
}
pushdown(u, l, r);
int mid = l + r >> 1;
if (nl <= mid)
{
modify(u << 1, l, mid, nl, nr);
}
if (nr > mid)
{
modify(u << 1 | 1, mid + 1, r, nl, nr);
}
pushup(u);
}
array<int, 3> query(int u, int l, int r, int nl, int nr)
{
if (l >= nl && r <= nr)
{
return {lc[u], rc[u], tr[u]};
}
pushdown(u, l, r);
int mid = l + r >> 1;
if (nr <= mid)
{
return query(u << 1, l, mid, nl, nr);
}
if (nl > mid)
{
return query(u << 1 | 1, mid + 1, r, nl, nr);
}
auto lson = query(u << 1, l, mid, nl, nr);
auto rson = query(u << 1 | 1, mid + 1, r, nl, nr);
array<int, 3> res;
if (lson[1] == rson[0])
{
res[2] = false;
}
else
{
res[2] = true;
}
if (lson[2] == 0 || rson[2] == 0)
{
res[2] = false;
}
res[0] = lson[0];
res[1] = rson[1];
return res;
}
void solve()
{
cin >> n >> q;
cin >> s;
s = ' ' + s;
build(1, 1, n);
while (q--)
{
int c, l, r;
cin >> c >> l >> r;
if (c == 1)
{
modify(1, 1, n, l, r);
}
else
{
auto res = query(1, 1, n, l, r);
if (res[2] == 0)
{
puts("No");
}
else
{
puts("Yes");
}
}
}
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
F - Breakdown
解题思路:
棋子只能从大权值点走向小权值点,所以图是\(DAG\)。
\(dp[u][w]:点u周围结点权值和为w时,1个棋子的最大操作步数。\)
\(f[u]:点u一个棋子的最大操作步数。\)
对结点按权值升序排序。从小权值结点开始计算\(1\)个棋子的最大步数。对每个结点做一次\(01\)背包。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const int inf = 1 << 30;
void solve()
{
int n, m;
cin >> n >> m;
vector<vector<int>> e(n + 1, vector<int>());
for (int i = 1; i <= m; i++)
{
int a, b;
cin >> a >> b;
e[a].push_back(b);
e[b].push_back(a);
}
vector<int> a(n + 1), w(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> w[i];
a[i] = i;
}
auto cmp = [&](int x, int y) -> bool
{
return w[x] < w[y];
};
sort(a.begin() + 1, a.end(), cmp);
vector<vector<ll>> dp(n + 1, vector<ll>(5010, 1));
vector<ll> f(n + 1, 1);
for (int i = 1; i <= n; i++)
{
int u = a[i];
for (auto v : e[u])
{
if (w[v] >= w[u])
{
continue;
}
for (int j = w[u] - 1; j >= 0; j--)
{
if (w[v] <= j)
{
dp[u][j] = max(dp[u][j], dp[u][j - w[v]] + f[v]);
f[u] = max(f[u], dp[u][j]);
}
}
}
}
ll ans = 0;
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
ans += f[i] * x;
}
cout << ans << endl;
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
G - Highest Ratio
解题思路:
\(pre_i:前缀和数组。\)
\[\frac{pre_r - pre_{k - 1}}{r - k + 1} \]我们将数组倒序,方便维护。
\[\frac{pre_i - pre_{j}}{i - j},(i > j) \]将\((i,pre_i)\)看作二维坐标上的一个点,不难发现我们要求最大斜率。
\(i和pre_i都是升序\),比较板子的斜率优化\(dp\)。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
void solve()
{
int n;
cin >> n;
vector<double> a(n + 1);
for (int i = n; i; i--)
{
cin >> a[i];
}
for (int i = 1; i <= n; i++)
{
a[i] += a[i - 1];
}
vector<int> q(n + 10);
int hh = 0;
int tt = 0;
q[0] = 0;
vector<double> ans;
for (int i = 1; i <= n; i++)
{
while (hh < tt && (a[i] - a[q[tt]]) * (i - q[tt - 1]) <= (a[i] - a[q[tt - 1]]) * (i - q[tt]))
{
tt--;
}
int j = q[tt];
ans.push_back((a[i] - a[j]) / (i - j));
q[++tt] = i;
}
reverse(ans.begin(), ans.end());
for (auto x : ans)
{
printf("%.10lf\n", x);
}
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
标签:AtCoder,return,Beginner,Contest,int,ll,long,using,define
From: https://www.cnblogs.com/value0/p/18024280