星环8.30笔试
ak了,代码做了点改动来更易读,有可能有地方有点小问题。
A
给你一个数组,每次操作你能选两个数,把较小的放到数组头部,较大的数放数组尾部,问最少多少次操作能将数组变为升序。
类似于贪心?或者说dp?感觉是乱搞搞。
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n;
cin >> n;
vector<int> dp(n + 1, 0);
int nm = n;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
dp[x] = dp[x - 1] + 1;
nm = min(nm, max(x - dp[x], n - x));
}
cout << nm << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) solve();
return 0;
}
B
给你一棵树,n个操作,每个操作有两种:
+ 1 x 表示输出x节点所有子节点权值和
+ 2 x 表示将x的最重子节点与自己旋转,最重子节点指的是它的所有子节点里子树节点数量最多的节点
模拟一下就行了
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
vector<int> g[MAXN];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
vector<long long> a(n);
for (auto &x : a) cin >> x;
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
a--, b--;
g[a].push_back(b);
g[b].push_back(a);
}
vector<long long> cnt(n), val(n), f(n);
auto cmp = [&](int x, int y) {
return cnt[x] != cnt[y] ? cnt[x] > cnt[y] : x < y;
};
vector<set<int, decltype(cmp)>> sons(n, set<int, decltype(cmp)>(cmp));
auto dfs = [&](auto &dfs, int now, int fa) -> void {
f[now] = fa;
for (auto x : g[now]) {
if (x != fa) {
dfs(dfs, x, now);
cnt[now] += cnt[x];
val[now] += val[x];
sons[now].insert(x);
}
}
cnt[now]++;
val[now] += a[now];
};
dfs(dfs, 0, -1);
int root = 0;
auto remove_from = [&](int x, int fa) {
sons[fa].erase(x);
val[fa] -= val[x];
cnt[fa] -= cnt[x];
};
auto insert_into = [&](int x, int fa) {
cnt[fa] += cnt[x];
val[fa] += val[x];
sons[fa].insert(x);
};
while (m--) {
int t, x;
cin >> t >> x;
t--;
x--;
if (t == 0) {
cout << val[x] << "\n";
} else {
if (sons[x].empty()) continue;
if (x == root) {
int t = *sons[x].begin();
remove_from(t, x);
insert_into(x, t);
root = t;
f[t] = -1;
f[x] = t;
continue;
}
int ff = f[x];
int s = *sons[x].begin();
remove_from(x, ff);
remove_from(s, x);
insert_into(x, s);
insert_into(s, ff);
f[x] = s;
f[s] = ff;
}
}
return 0;
}
C
给n个点,两个点距离表示为他们横纵坐标差的绝对值的最小值。求任意两点最大距离。
二分答案
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
vector<array<long long, 2>> v(n);
for (auto &x : v) cin >> x[0] >> x[1];
sort(v.begin(), v.end());
vector<int> ymina(n), ymaxa(n);
vector<int> yminb(n), ymaxb(n);
long long ymin = v[0][1];
long long ymax = v[0][1];
for (int i = 0; i < n; i++) ymina[i] = ymin = min(ymin, v[i][1]);
for (int i = 0; i < n; i++) ymaxa[i] = ymax = max(ymax, v[i][1]);
ymin = v.back()[1];
ymax = v.back()[1];
for (int i = n - 1; i >= 0; i--) yminb[i] = ymin = min(ymin, v[i][1]);
for (int i = n - 1; i >= 0; i--) ymaxb[i] = ymax = max(ymax, v[i][1]);
long long l = 0, r = 2e9 + 1;
auto check = [&](long long t) {
int r = 0;
for (int i = 0; i < n; i++) {
while (r < n && v[r][0] - v[i][0] < t) r++;
if (r == n) return false;
long long a[] = {ymina[i], ymaxa[i]};
long long b[] = {yminb[r], ymaxb[r]};
for (auto x : a)
for (auto y : b)
if (abs(x - y) >= t) return true;
}
return false;
};
while (l < r) {
long long mid = (l + r) / 2;
if (l + 1 == r) {
if (check(r))
l++;
else
r--;
}
if (check(mid))
l = mid;
else
r = mid;
}
cout << l;
return 0;
}