A - Sekiro
题意
初始有\(n\)个金币,死了\(m\)次,死一次\(n = \lceil \frac n 2 \rceil\)。求最后的金币数。
思路
模拟。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long longvoid solve()
{int n, m;cin >> n >> m;while (m-- && n > 1){n = (n + 1) >> 1;}cout << n << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T = 1;cin >> T;while (T--){solve();}return 0;
}
B - Median
题意
\(n\)个数(\(n\)是奇数),\(m\)对关系(\(u v\)表示\(u > v\)),对于第\(i\)个元素,给每个元素赋值,能使它成为中位数就输出\(1\),否则输出\(0\)。
思路
一条关系可以看作一条有向边,由大的指向小的,得到一张有向图,先判断有无环,有环说明情况不存在全为\(0\),可用\(bfs\)或\(dfs\)判断,同时记录该点的前继和后继,若该点为中位数,说明该点的前继和后继都不超过\(\frac n 2\)。
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long longconst int mxn = 110;int n, m, cnt;
vector<int>g1[mxn], g2[mxn];
int up[mxn], low[mxn], deg[mxn], vis[mxn];void dfs1(int u, int fa)
{vis[u] = 1;for (auto v : g2[u]) {if (!vis[v]) {cnt++;dfs1(v, u);}}
}void dfs2(int u, int fa)
{vis[u] = 1;for (auto v : g1[u]){if (!vis[v]){cnt++;dfs2(v, u);}}
}bool topo() {cnt = 0;queue<int>q;for (int i = 1; i <= n; i++) {if (deg[i] == 0){q.push(i);}}while (!q.empty()) {int u = q.front();q.pop();cnt++;for (auto v : g1[u]){if (--deg[v] == 0){q.push(v);}}}return cnt == n;
}void init()
{for (int i = 1; i <= n; i++) {g1[i].clear();g2[i].clear();deg[i] = 0;up[i] = 0;low[i] = 0;}
}void solve()
{cin >> n >> m;init();for (int i = 1; i <= m; i++) {int u, v;cin >> u >> v;g1[u].push_back(v);g2[v].push_back(u);deg[v]++;}if (!topo()) {for (int i = 1; i <= n; i++) {putchar('0');}putchar('\n');return;}for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++){vis[j] = 0;}cnt = 0;dfs1(i, -1);up[i] = cnt;for (int j = 1; j <= n; j++) {vis[j] = 0;}cnt = 0;dfs2(i, -1);low[i] = cnt;}for (int i = 1; i <= n; i++) {if (up[i] < (n + 1) / 2 && low[i] < (n + 1) / 2) {putchar('1');}else {putchar('0');}}putchar('\n');
}signed main()
{ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int T;cin >> T;while (T--){solve();}return 0;
}
C - Tokens on the Segments
题意
\(n\)条线段,其中第\(i\)段的端点是\((l_i, i)\)和\((r_i, i)\),在平面的整数点放标记,但是标记的\(x\)坐标必须彼此不同。问最多有多少条线段上有标记。
思路
按如下方法将线段存入小根堆:左端点靠前的在前,左端点一样的,右端点靠前的在前。从最左边的线段的左端点开始计数,用指针记录当前位置。指针右移,同时更新其他线段的左端点(因为标记的\(x\)不能相同),到新的线段就\(ans++\),当前位置没有线段就直接移动到下一条线段。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long longstruct edge
{int l, r;bool operator < (const edge& a) const{if (l == a.l){return r > a.r;}return l > a.l;}
};void solve()
{int n;cin >> n;priority_queue<edge, vector<edge>> q; // 小根堆for (int i = 0; i < n; i++){int l, r;cin >> l >> r;q.push({ l,r });}int now = 1, ans = 0; // 当前可以标记的位置while (!q.empty()){int l = q.top().l;int r = q.top().r;q.pop();if (r >= now) // 右端点>=now就可以标记,且尽量往左标—,所以要更新左端点{ans++;if (l < now) // 标记处在线段左边(与上一条之间有空){now = l + 1;}else{now++;}}while (q.size() && q.top().l == l) // 更新左端点{edge t = q.top();q.pop();t.l++; // 前推1if (t.l <= t.r) // 仍然是线段(或者点){q.push(t);}}}cout << ans << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T = 1;cin >> T;while (T--){solve();}return 0;
}
D - Stones in the Bucket
题意
\(n\)个桶,第\(i\)个桶里有\(a_i\)个石头。两种操作:从非空同种一走一个石头、把一个桶里的石头移到另一个桶里。问使得所有桶里石头数相同所需的最小操作数。
思路
模拟。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long longvoid solve()
{int n, sum = 0;cin >> n;vector<int> v(n);for (int i = 0; i < n; i++){cin >> v[i];sum += v[i];}if (n == 1){cout << 0 << endl;return;}int ans = sum % n; // 剩下的sum /= n; // 平均分for (int i = 0; i < n; i++){if (v[i] != sum && v[i] < sum) // 少的多的看一半就行{ans += (sum - v[i]);}}cout << ans << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T = 1;cin >> T;while (T--){solve();}return 0;
}
E - BaoBao Loves Reading
题意
思路
代码
点击查看代码
F - Game on a Graph
题意
给定\(n\)个顶点\(m\)条边的简单连通图,\(k\)个人已知分队,轮流删边,使得图不连通的队伍输。两个队伍用最佳策略游戏,问哪队赢。
思路
连通图至少有\(n-1\)条边,也就是说谁能删\(m-(n-1)\)条边。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long longvoid solve()
{int n, m, k;string s;cin >> k >> s >> n >> m;for (int i = 0; i < m; i++){int u, v;cin >> u >> v;}int idx = (m - n + 1) % k;cout << (s[idx] == '1' ? '2' : '1') << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T = 1;cin >> T;while (T--){solve();}return 0;
}
B - Median
题意
思路
代码
点击查看代码
H - Wandering Robot
题意
一个在\((0,0)\)机器人每次能够上/下/左/右移动一个单位,用\(U/D/L/R\)表示。已知长度为\(n\)的操作序列,以及重复操作了\(k\)次,求移动过程中机器人到点\((0,0)\)的曼哈顿距离的最大值。
曼哈顿距离:\(|x1−x2|+|y1−y2|\)。
思路
答案一定在第一次操作或第\(k\)次操作中,因为如果第一轮结束导致答案增大,那就会一直增大直至第\(k\)次操作结束;如果减小,之后也会一直减小。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long longint n, k;
string cmd;void move(int& x, int& y, int& ans)
{for (int i = 0; i < n; i++){switch (cmd[i]){case 'U':y++;break;case 'D':y--;break;case 'L':x--;break;case 'R':x++;break;default:break;}ans = max(ans, abs(x) + abs(y));}
}void solve()
{cin >> n >> k >> cmd;int x = 0, y = 0, ans = 0;move(x, y, ans);int kx = (k - 1) * x, ky = (k - 1) * y; // (k - 1)次操作后的坐标move(kx, ky, ans);cout << ans << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T = 1;cin >> T;while (T--){solve();}return 0;
}
K - Happy Equation
题意
思路
代码
点击查看代码
M - Calandar
题意
定义一年有\(12\)个月,每月\(30\)天,每周\(5\)天(周五之后是周一)。已知今天是\(y_1\)年\(m_1\)月\(d_1\)日和周几,求\(y_2\)年\(m_2\)月\(d_2\)日是周几。
思路
算日期差值后取模即可。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long longstring week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };void solve()
{int y1, y2, m1, m2, d1, d2;string w;cin >> y1 >> m1 >> d1 >> w >> y2 >> m2 >> d2;int num1 = y1 * 12 * 30 + m1 * 30 + d1;int num2 = y2 * 12 * 30 + m2 * 30 + d2;int dt = (num2 - num1) % 5;int id = 0;for (int i = 0; i < 5; i++){if (w == week[i]){id = i;break;}}cout << week[(id + dt + 5) % 5] << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T = 1;cin >> T;while (T--){solve();}return 0;
}