第三届“传智杯”全国大学生IT技能大赛
第三届“传智杯”全国大学生IT技能大赛
T160507 A - 课程报名
提议模拟, 就不放代码了
B - 期末考试成绩
模拟题意
T160509 C - 志愿者
自己手写个排序函数就行
T160510 D - 终端
写个map存每个字串的时间, 输出的时候先放到另一个容器里排序输出即可
T160513 E - 运气
爆搜
T160511 F - 游戏
\(O(n^2)\) 暴力找能和自己连边的最小值的点, 正反来一次
就成了最小生成树
vector<pair<int, PII>> e;
int c1, c2, f[N];
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
int main() {
IOS; cin >> n >> c1 >> c2;
rep (i, 1, n) cin >> f[i];
rep (i, 1, n) {
int wx = 2e9, s = 0;
rep (j, i + 1, n) {
if (f[i] == f[j]) continue;
int w = __builtin_popcount(f[i] ^ f[j]) == 1 ? c1 : c2;
if (wx > w) wx = w, s = j;
}
if (wx != 2e9) e.pb({ wx, { i, s } });
}
per (i, n, 1) {
int wx = 2e9, s = 0;
per (j, i - 1, 1) {
if (f[i] == f[j]) continue;
int w = __builtin_popcount(f[i] ^ f[j]) == 1 ? c1 : c2;
if (wx > w) wx = w, s = j;
}
if (wx != 2e9)e.pb({ wx, { i, s } });
}
rep (i, 1, n) f[i] = i;
sort(all(e)); ll ans = 0;
for (auto &i : e) {
int x = find(i.se.fi), y = find(i.se.se);
if (x == y) continue;
ans += i.fi; f[x] = y;
}
cout << ans;
return 0;
}
T160512 G - 森林
还是并查集, 没点创意
int fa[N], s[N], e[N][2], op[N][2], ans[N], cnt;
bool pd[N];
stack<int> a[N];
int find(int x) {
int i = x, j, r = x;
while (fa[r] != r) r = fa[r];
while (fa[i] != r) j = fa[i], fa[i] = r, i = j;
return r;
}
void unit(int x, int y) {
x = find(x), y = find(y);
if (x == y) return;
fa[x] = y; s[y] += s[x];
}
int main() {
IOS; cin >> n >> m;
rep (i, 1, n) {
int t; cin >> t;
a[i].push(t); fa[i] = i;
}
rep (i, 1, n - 1) cin >> e[i][0] >> e[i][1];
rep (i, 1, m) {
cin >> op[i][0] >> op[i][1];
if (op[i][0] == 1) pd[op[i][1]]=1;
else if (op[i][0] == 2) { cin >> t; a[op[i][1]].push(t); }
}
rep (i, 1, n) s[i] = a[i].top();
rep (i, 1, n - 1) if(!pd[i]) unit(e[i][0], e[i][1]);
per (i, m, 1) {
switch (op[i][0]) {
case 1: unit(e[op[i][1]][0], e[op[i][1]][1]); break;
case 2:
s[find(op[i][1])]-=a[op[i][1]].top();
a[op[i][1]].pop();
s[find(op[i][1])]+=a[op[i][1]].top();
break;
case 3: ans[++cnt]=s[find(op[i][1])]; break;
}
}
per (i, cnt, 1) cout << ans[i] << '\n';
return 0;
}