Codeforces Round #670 (Div. 2)
A
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e3 + 5;
int n, m, _, k;
int a[105];
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; m = -1;
rep(i, 0, 100) a[i] = 0;
rep(i, 1, n) cin >> k, a[k]++;
rep(i, 0, 101)
if (a[i] == 0 && m == -1) { m = i * 2; break; }
else if (a[i] == 1 && m == -1) m = i;
else if (a[i] == 0) { m += i; break; }
cout << m << '\n';
}
return 0;
}
B
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e5 + 5;
int n, m, _, k;
VI a;
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; a.resize(n);
for (auto &i : a) cin >> i;
sort(all(a));
ll ans = -1e18;
rep (i, 0, 5) {
ll cur = 1;
rep (j, 0, i - 1) cur *= a[j];
rep (j, 1, 5 - i) cur *= a[n - j];
ans = max(ans, cur);
}
cout << ans << '\n';
}
return 0;
}
C
wa 到自闭, 没考虑到 1 -2 不一定有边, 一直在找其他错误
最多两个重心, 必定是相连接的, 从一个重心连接的其他子树中抽一个 叶子节点, 连在另一个重心即可
一个重心, 随便段意条边在连接, 1-2不一定有边!!!!!!
代码有点丑, c为啥这么长啊
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e5 + 5;
int n, m, _, k;
int h[N], to[N << 1], ne[N << 1], tot;
int siz[N], mx;
VI a;
void add(int u, int v) {
ne[++tot] = h[u]; to[h[u] = tot] = v;
}
void dfs(int x, int fa) {
siz[x] = 1;
int mxs = 0;
for (int i = h[x]; i; i = ne[i]) {
int y = to[i];
if (y == fa) continue;
dfs(y, x);
mxs = max(mxs, siz[y]);
siz[x] += siz[y];
}
mxs = max(mxs, n - siz[x]);
if (mxs < mx) mx = mxs, a.resize(0), a.pb(x);
else if (mx == mxs) a.pb(x);
}
int dfss(int x, int fa) {
if (!ne[h[x]]) {
cout << x << ' ' << fa << '\n';
return x;
}
for (int i = h[x]; i; i = ne[i]) {
int y = to[i];
if (y == fa) continue;
return dfss(y, x);
}
return 0;
}
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; tot = 0; mx = 1e9;
a.resize(0);
rep(i, 1, n) h[i] = siz[i] = 0;
rep(i, 2, n) {
int u, v; cin >> u >> v;
add(u, v); add(v, u);
}
dfs(1, 0);
if (a.size() == 2) {
if (ne[h[a[0]]]) {
int c = dfss(a[0], a[1]);
cout << c << ' ' << a[1] << '\n';
}
else {
int c = dfss(a[1], a[0]);
cout << c << ' ' << a[0] << '\n';
}
}
else {
int c = to[h[1]];
cout << c << ' ' << "1\n1 " << c << '\n';
}
}
return 0;
}
D
好题, 差分和前缀和都用到了
首先要想清楚一点, a[i + 1] - a[i] < 0, 则存在 b[i] == b[i + 1] (不懂得接着往下看, 应该也能理解)
b[i + 1] - b[i] >= d[i](d[i] >= 0), c[i] = a[i] - b[i] >= a[i + 1] - b[i + 1] = c[i + 1]
所以 a[i + 1] - a[i] <= d[i](d[i] > 0, 第一句话也应该能理解了)
\(max(b[n], c[1]) = max(b[1] + \sum_{i=1}^{n - 1} d[i], a[1] - b[1])\)
式子中变量只有 b[1], $ min(b[1] + \sum_{i=1}^{n - 1} d[i], a[1] - b[1]) $ 因为奇偶问题 要么相差0, 要么相差1
那 d[i] 怎么取值呢, 想要最大值最小 当然是 d[i] = a[i + 1] - a[i],
区间修改, 只是修改了两个点的 d[l - 1], d[r], 判断合法区间 和 处理两个点的修改就行了, 具体看代码
ps: 不要想着弄个 d[0] = a[1], 把 a[1] 从式子去掉, d[i] 的前缀和加上 d[0], 要注意到我们不论 d[0] 是都大于0我们都要取得, 其他 d[i], 我们是要取 max(0, d[i])的
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e5 + 5;
int n, m, _, k;
ll a[N], d[N], s;
int main() {
IOS; cin >> n;
rep (i, 1, n) cin >> a[i], d[i - 1] = a[i] - a[i - 1];
rep (i, 1, n - 1) s += max(d[i], 0ll);
cout << (a[1] + s + 1 >> 1) << '\n';
for (cin >> _; _; --_) {
int l, r, x; cin >> l >> r >> x;
if (l > 1) {
s -= max(d[l - 1], 0ll); d[l - 1] += x;
s += max(0ll, d[l - 1]);
}
if (r < n) {
s -= max(d[r], 0ll); d[r] -= x;
s += max(0ll, d[r]);
}
if (l == 1) a[1] += x;
cout << (a[1] + s + 1 >> 1) << '\n';
}
return 0;
}
E
分块, 不然次数不够
1e5, 以内质数 9592, 每个操作两次必定不行
假设 x 只剩下一个质因数不知道, 那么就可以用分块
记录每个区间删除质数后应该剩下的数 "A 1", 发现少删除1个数, 那么最后一个质因数就在这个分块区间内
怎么让 x 只剩下一个质因数呢?
虽然用不到
引理 x的大于 \(\sqrt{x}\) 的质因数 最多有一个
而 小于 \(\sqrt{1e5}\) 的 质因数就 65个, 可以暴力求,
再加上一些优化, 并不需要跑完着65个, 加上中间判断的一些小优化, 是超不了 1e4 的询问的
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e5 + 5;
int n, m, _, k = 1;
int prime[N], tot;
bool v[N];
ll ans = 1;
void ask(int id, int &x) {
cout << char('A' + id) << ' ' << x << endl;
cin >> x;
}
void init(int n) {
rep (i, 2, n) {
if (!v[i]) prime[++tot] = i;
rep (j, 1, tot) {
if (prime[j] > n / i) break;
v[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
void print() {
cout << "C " << ans << endl;
}
int main() {
IOS; init(1e5); cin >> n;
for (int &i = k; i <= tot; ++i)
if (prime[i] > n / ans) { print(); return 0; }
else if (prime[i] <= n / ans / prime[i]) {
ll cur = prime[i], res = 1;
while (cur <= n / ans) {
ask(1, m = cur); if (!m) break;
ask(0, m = cur); if (!m) break;
res = cur, cur *= prime[i];
}
ans *= res;
}
else break;
ask(0, m = 1);
int l = k, r = k, d, ls = m, s = 0;
while (r < tot && prime[r + 1] <= n / ans) ++r;
d = ceil(sqrt(r - l + 1));
for (int i = l; i <= r; ++i) {
ask(1, m = prime[i]); s += m;
if (i - l + 1 != d && i != r) continue;
ask(0, m = 1);
if (ls - s == m) { ls = m, s = 0, l += d; continue; }
rep (j, l, i) {
ask(0, m = prime[j]);
if (m) { ans *= prime[j]; print(); return 0; }
}
}
print();
return 0;
}