- 周末要打天梯赛和蓝桥杯,过了这周总算事情少一点了
- 最近精神内耗好严重
ATC - abc348
A - Penalty Kick
输出题
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n;
cin >> n;
for (int i = 1; i <= n; i ++ )
{
if (i % 3 == 0) cout << 'x';
else cout << 'o';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}
B - Farthest Point
纯暴力
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
int dist(int x1, int y1, int x2, int y2)
{
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
}
void solve()
{
int n;
cin >> n;
vector<PII> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i].first >> a[i].second;
for (int i = 0; i < n; i ++ )
{
int maxx = 0, pos = -1;
for (int j = 0; j < n; j ++ )
{
if (dist(a[i].first, a[i].second, a[j].first, a[j].second) > maxx) maxx = dist(a[i].first, a[i].second, a[j].first, a[j].second), pos = j;
}
cout << pos + 1 << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}
C - Colorful Beans
暴力,找到每种颜色最小值里的最大值
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<int, string> PIS;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n;
cin >> n;
map<int, vector<int>> mp;
for (int i = 0; i < n; i ++ )
{
int a, c;
cin >> a >> c;
mp[c].push_back(a);
}
int ans = 0;
for (auto t : mp)
{
sort(t.second.begin(), t.second.end());
ans = max(ans, t.second[0]);
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}
D - Medicines on Grid(dijkstra)
一开始把题目看错了,走到有药品的格子,是把自身能量变成药品值
那就很简单了,在 dijkstra 更新状态的时候更新一下如果当前格有药品的情况即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<int, string> PIS;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
void solve()
{
int h, m;
cin >> h >> m;
vector<vector<char>> g(h + 1, vector<char>(m + 1));
int stx, sty, edx, edy;
for (int i = 1; i <= h; i ++ )
{
for (int j = 1; j <= m; j ++ )
{
cin >> g[i][j];
if (g[i][j] == 'S') stx = i, sty = j;
if (g[i][j] == 'T') edx = i, edy = j;
}
}
int n;
cin >> n;
vector<vector<int>> w(h + 1, vector<int>(m + 1));
vector<vector<int>> dist(h + 1, vector<int>(m + 1, -1));
for (int i = 0; i < n; i ++ )
{
int r, c, e;
cin >> r >> c >> e;
w[r][c] += e;
}
priority_queue<PIII> pq;
if (w[stx][sty] == 0)
{
cout << "No\n";
return;
}
pq.push({w[stx][sty], {stx, sty}});
while (pq.size())
{
auto t = pq.top();
pq.pop();
int ery = t.first, x = t.second.first, y = t.second.second;
if (dist[x][y] < w[x][y])
{
dist[x][y] = w[x][y];
pq.push({dist[x][y], {x, y}});
continue;
}
for (int i = 0; i < 4; i ++ )
{
int nx = x + dx[i], ny = y + dy[i];
if (nx <= 0 || nx > h || ny <= 0 || ny > m) continue;
if (st[nx][ny] || g[nx][ny] == '#') continue;
if (dist[nx][ny] < ery - 1)
{
dist[nx][ny] = ery - 1;
pq.push({dist[nx][ny], {nx, ny}});
}
}
}
if (dist[edx][edy] == -1) cout << "No\n";
else cout << "Yes\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}
E - Minimize Sum of Distances(换根dp)
还算是比较典的换根dp(能让我看出来那就是非常典的换根dp
先跑一遍dfs处理每个结点子树的大小
然后计算选择第一个点的答案
f[i]
表示第 i 个点为根的答案
换之前的根是 u,换之后的是 ver,从 u 换到 ver ,所有在 ver 子树中的结点到根的距离加一,其他结点到根的距离减一
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<int, string> PIS;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n;
cin >> n;
vector<vector<int>> g(n + 1);
for (int i = 0; i < n - 1; i ++ )
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> c(n + 1), sz(n + 1), dist(n + 1, INF);
for (int i = 1; i <= n; i ++ ) cin >> c[i];
function<void(int, int)> dfs1 = [&](int u, int fa)
{
sz[u] = c[u];
for (int i = 0; i < g[u].size(); i ++ )
{
int j = g[u][i];
if (j == fa) continue;
dfs1(j, u);
sz[u] += sz[j];
}
};
dfs1(1, -1);
dist[1] = 0;
queue<int> q;
q.push(1);
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < g[t].size(); i ++ )
{
int ver = g[t][i];
if (dist[ver] > dist[t] + 1)
{
dist[ver] = dist[t] + 1;
q.push(ver);
}
}
}
int ans = INF;
vector<int> f(n + 1, INF);
f[1] = 0;
for (int i = 1; i <= n; i ++ ) f[1] += c[i] * dist[i];
function<void(int, int)> dfs2 = [&](int u, int fa)
{
ans = min(ans, f[u]);
for (int i = 0; i < g[u].size(); i ++ )
{
int ver = g[u][i];
if (ver == fa) continue;
f[ver] = min(f[ver], f[u] - sz[ver] + sz[1] - sz[ver]);
dfs2(ver, u);
}
};
dfs2(1, -1);
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}
F - Oddly Similar(bitset优化)
计算不同状态的个数,且状态只有两种,可以利用bitset
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<int, string> PIS;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, m;
cin >> n >> m;
vector<vector<int>> g(n, vector<int>(m));
vector<vector<bitset<2010>>> a(m, vector<bitset<2010>>(1010));
for (int i = 0; i < n; i ++ )
{
for (int j = 0; j < m; j ++ )
{
int x; cin >> x;
g[i][j] = x;
a[j][x][i] = 1;
}
}
int ans = 0;
for (int i = 0; i < n; i ++ )
{
bitset<2010> bt = {};
for (int j = 0; j < m; j ++ )
{
bt ^= a[j][g[i][j]];
}
bt[i] = 0;
ans += bt.count();
}
cout << ans / 2 << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}
G - Max (Sum - Max)(主席树+二分)
很明显先按b排序,然后枚举b,再找b和b之前对应的a中最大的k个值,这个用主席树维护
同时这里又有个二分性,如果在前 j 个 b 中我们选择了第 i 个 b ,那么我们称 i 是对于 j 的最优决策点,可以发现,最优决策点一定是非递减的,所以套个二分处理(其实这里也没有理解的很好,但主席树真的调了超级无敌久)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 10, INF = 1000000000, inf = 1e18;
struct node {
int ls, rs;
int sz;
int sum;
};
node tr[N * 35];
int idx = 0;
int rt[N];
int n, ans[N];
pair<int, int> v[N];
bool cmp(PII x, PII y)
{
return x.second < y.second;
}
int add(int p, int l, int r, int x)
{ // 插入
int q = ++ idx;
if (p != 0) tr[q] = tr[p];
if (l == r)
{
tr[q].sz += 1;
tr[q].sum += x;
return q;
}
int mid = l + r >> 1;
if (x <= mid) tr[q].ls = add(tr[p].ls, l, mid, x);
else tr[q].rs = add(tr[p].rs, mid + 1, r, x);
tr[q].sz = tr[tr[q].ls].sz + tr[tr[q].rs].sz;
tr[q].sum = tr[tr[q].ls].sum + tr[tr[q].rs].sum;
return q;
}
int query(int p, int l, int r, int k)
{
if (p == 0) return 0;
if (l == r) return l * k;
int mid = l + r >> 1;
if (tr[tr[p].rs].sz >= k) return query(tr[p].rs, mid + 1, r, k);
else return tr[tr[p].rs].sum + query(tr[p].ls, l, mid, k - tr[tr[p].rs].sz);
}
int ask(int k, int x)
{
return query(rt[x - 1], -INF, INF, k - 1) + v[x].first - v[x].second;
}
void work(int l, int r, int L, int R)
{
if (l > r) return;
int mid = l + r >> 1;
ans[mid] = -inf;
int pos;
for (int i = max(mid, L); i <= R; i ++ )
{
int tmp = ask(mid, i);
if (tmp > ans[mid]) ans[mid] = tmp, pos = i;
}
work(l, mid - 1, L, pos);
work(mid + 1, r, pos, R);
}
signed main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> v[i].first >> v[i].second;
}
sort(v + 1, v + 1 + n, cmp);
for (int i = 1; i <= n; i++)
{
rt[i] = add(rt[i - 1], -INF, INF, v[i].first);
}
work(1, n, 1, n);
for (int i = 1; i <= n; i++)
{
cout << ans[i] << endl;
}
return 0;
}
CF-1286B-Numbers on Tree
有意思的构造,构造题还是容易想复杂啊
想到了把每个点赋值 [1, n]
,但是没注意到 n 挺小的完全暴力查找就可以,一直在想怎么二分找值。。。
树上构造的大致思路还是dfs构造单点
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n;
cin >> n;
vector<int> p(n + 1), c(n + 1);
vector<vector<int>> g(n + 1);
int root = 0;
for (int i = 1; i <= n; i ++ )
{
cin >> p[i] >> c[i];
g[p[i]].push_back(i);
if (p[i] == 0) root = i;
}
vector<int> sz(n + 1);
function<void(int, int)> dfs1 = [&](int u, int fa)
{
sz[u] = 1;
for (int i = 0; i < g[u].size(); i ++ )
{
int j = g[u][i];
if (j == fa) continue;
dfs1(j, u);
sz[u] += sz[j];
}
};
dfs1(root, -1);
vector<int> ans(n + 1);
vector<int> st(n + 1);
auto find_a = [&](int x)
{
int cnt = 0;
for (int i = 1; i <= n; i ++ )
{
if (!st[i])
{
cnt ++ ;
if (cnt == x + 1)
{
st[i] = true;
return i;
}
}
}
return (i64)-1;
};
function<bool(int, int)> dfs2 = [&](int u, int fa)
{
int tmp = find_a(c[u]);
if (tmp == -1) return false;
if (sz[u] - 1 < c[u]) return false;
ans[u] = tmp;
for (int i = 0; i < g[u].size(); i ++ )
{
int ver = g[u][i];
if (ver == fa) continue;
if (!dfs2(ver, u)) return false;
}
return true;
};
if (dfs2(root, -1))
{
cout << "YES\n";
for (int i = 1; i <= n; i ++ ) cout << ans[i] << ' ';
}
else cout << "NO\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}
ATC - abc350
C - Airport Code
暴力判断
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
string s, t;
cin >> s >> t;
int flag = 0;
for (int i = 0; i < s.size(); i ++ )
{
if (s[i] >= 'a' && s[i] <= 'z') s[i] += 'A' - 'a';
if (s[i] == t[flag]) flag ++ ;
if (flag == 3)
{
cout << "Yes\n";
return;
}
}
if (flag == 2 && t[2] == 'X') cout << "Yes\n";
else cout << "No\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}
D - Divide Interval(贪心)
首先很容易想到要让每个 2 i 2^i 2i 尽可能大(所以 j × 2 i j\times2^i j×2i 里的 j 必须是奇数,因为偶数可以直接再出一个2),但让 2 i 2^i 2i 尽可能大的同时不要忘了让 l + 2 i l+2^i l+2i 不超过 r r r,找到同时满足这两个条件的一个数,再往后贪心下去
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int l, r;
cin >> l >> r;
vector<PII> ans;
while (l < r)
{
int p1 = 1;
int p2 = l;
while (p2 % 2 == 0 && l + p1 <= r)
{
p2 /= 2;
p1 *= 2;
}
while (l + p1 > r)
{
p1 /= 2;
}
ans.push_back({l, l + p1});
l = l + p1;
}
cout << ans.size() << '\n';
for (auto t : ans) cout << t.first << ' ' << t.second << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
}