A
void solve() {
n = 12;
int ans = 0;
string s;
FOR(i, n) qr(s), ans += SZ(s) == i;
pr2(ans);
}
B
void solve() {
string s;
qr(s);
n = SZ(s);
rep(i, 0, n - 1) a[s[i]] = i;
rep(i, 'B', 'Z') m += abs(a[i] - a[i - 1]);
pr2(m);
}
C
void solve() {
qr(n);
VT<int> a(n), b(n);
qr(a, b);
pr2(ranges::max(a) + ranges::max(b));
}
D
把反向边加上,边权取负, 然后dfs即可.
int n, m;
ll v[N];
bool vis[N];
VT<pii> e[N];
void dfs(int x) {
if(vis[x]) return;
vis[x] = 1;
for(auto [y, z]: e[x]) {
v[y] = v[x] + z;
dfs(y);
}
}
void solve() {
qr(n, m);
int x, y, z;
FOR(i, m) {
qr(x, y, z);
e[x].pb({y, z});
e[y].pb({x, -z});
}
FOR(i, n) dfs(i);
FOR(i, n) pr1(v[i]);
}
E
对每个人二分增加的票数, 判断是否能赢.
当他此时票数为 w w w, 则有其他 m m m 个人的票数 > w >w >w 时, 他会输.
这个时候,可以二分一下 ≤ w \le w ≤w 的分界位置 p p p , 那么 [ n − m + 1 , p ] [n-m+1,p] [n−m+1,p] 大的人需要移动到 w + 1 w+1 w+1, 用前缀和计算这个区间的总需求票数即可.
特别地, 如果他一开始就是前 m m m 大的话, 需要把他剔除, 查询区间变为 [ n − m , p ] [n-m,p] [n−m,p].
int n, m, p[N];
ll a[N], b[N], s[N], ans[N];
void solve() {
ll k;
qr(n, m, k);
FOR(i, n) qr(a[i]), p[i] = i;
if(m == n) {
FOR(i, n) pr1(0);
return;
}
sort(p + 1, p + n + 1, [&](int x, int y) {return a[x] < a[y];});
FOR(i, n) s[i] = s[i - 1] + (b[i] = a[p[i]]);
ll res = k - s[n];
FOR(i, n) {
int x = p[i];
auto check = [&](ll v) -> bool {
ll w = v + a[x] + 1;
if(w <= b[n - m]) return 0;
int l = n - m, r = n, mid;
while(l < r) {
mid = (l + r + 1) >> 1;
if(b[mid] < w) l = mid;
else r = mid - 1;
}
v = res - v;
if(i > n - m) {
v -= w * (l - (n - m)) - (s[l] - s[n - m - 1] - b[i]);
}
else {
v -= w * (l - (n - m)) - (s[l] - s[n - m]);
}
return v < 0;
};
ll l = 0, r = res, mid;
while(l < r) {
mid = (l + r) >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
ans[x] = !check(l) ? -1: l;
}
FOR(i, n) pr1(ans[i]);
}
F
考虑同一个物品 ( w i , v i ) (w_i,v_i) (wi,vi) 取 k k k 次和 k − 1 k-1 k−1 次的差分, v ’ = k v − k 2 − [ ( k − 1 ) v − ( k − 1 ) 2 ] = v − 2 k − 1 v’=kv-k^2-[(k-1)v-(k-1)^2]=v-2k-1 v’=kv−k2−[(k−1)v−(k−1)2]=v−2k−1. 那么可以视作有一个物品重量为 w i w_i wi, 价值为 v ’ v’ v’.
然后, 对于相同重量的物品, 我们取价值大的肯定更优.
对于重量 w w w, 至多加入 m w \dfrac m w wm 个, 那么我们只需要排序取前 m w \dfrac m w wm 大加入背包即可.
总复杂度 O ( n m + m 2 log m ) O(nm + m^2 \log m) O(nm+m2logm).
int n, m;
ll f[N];
void add(int x, int y) {
REP(i, x, m)
cmax(f[i], f[i - x] + y);
}
void solve() {
qr(n, m);
memset(f, -63, sizeof f);
f[0] = 0;
int x, y;
VT v(m + 1, VT<int>());
while(n--) {
qr(x, y); y--;
for(int i = x; i <= m; i += x)
v[x].pb(y), y -= 2;
}
FOR(i, m) {
auto &a = v[i];
n = m / i;
if(SZ(a) > n) nth_element(a.begin(), a.begin() + SZ(a) - n, a.end());
for(auto j: a | views::reverse) {
add(i, j);
if(!--n) break;
}
}
pr2(*max_element(f, f + m + 1));
}
G
有两个点集 X , Y X, Y X,Y, 需要他们两两配对, 且相连线段不交. 最后给出配对方案.(没有点重合, 三点共线的情况. n < = 300 n<=300 n<=300.)
如图, 相交的话,长度会比不交大.
那么我们可以考虑求图的最小权匹配, 边权为欧氏距离.
最后得到的匹配就是答案.
代码1为KM算法, 代码2为暴力置换边.(代码2其实更短且更快…)
Code1:
#include <bits/stdc++.h>
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define pll pair<ll, ll>
#define VT vector
#define VA valarray
#define pb push_back
#define SZ(a) ((int)a.size())
#define all(a) (a).begin(), (a).end()
#define TP template <class o>
#define TPP template <typename t1, typename t2>
#define rep(i, a, b) for (int i = a, i##_ = b; i <= i##_; i++)
#define REP(i, a, b) for (int i = b, i##_ = a; i >= i##_; i--)
#define FOR(i, n) rep(i, 1, n)
#define debug(x) cerr << #x << ' ' << '=' << ' ' << x << endl
using namespace std;
typedef long double db;
typedef long double ld;
typedef unsigned ui;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 i128;
typedef unsigned __int128 u128;
TPP istream &operator>>(istream &cin, pair<t1, t2> &a) {return cin >> a.first >> a.second; }
TP istream &operator>>(istream &cin, VT<o> &a) {for(o &i: a) cin >> i; return cin; }
TP istream &operator>>(istream &cin, VA<o> &a) {for(o &i: a) cin >> i; return cin;}
TP void qr(o& x) {cin >> x;}
template <class o, class... O> void qr(o& x, O&... y) { qr(x), qr(y...); }
TP void pr1(o x) { cout << x << ' ';}
template <class o, class... O> void pr1(o x, O... y) { pr1(x), pr1(y...); }
TP void pr2(o x) { cout << x << endl;}
template <class o, class... O> void pr2(o x, O... y) { pr2(x), pr2(y...); }
TPP ostream& operator <<(ostream &cout, pair<t1, t2> &a) {
return cout << a.first << ' ' << a.second;
}
TP ostream& operator <<(ostream &cout, VA<o> &a) {
int n = SZ(a); if(!n) return cout;
cout << a[0];
for(int i = 1; i < n; i++) cout << ' ' << a[i];
return cout;
}
TP ostream& operator <<(ostream &cout, VT<o> &a) {
int n = SZ(a); if(!n) return cout;
cout << a[0];
for(int i = 1; i < n; i++) cout << ' ' << a[i];
return cout;
}
TPP ostream& operator <<(ostream &cout, VT<pair<t1, t2>> &a) {
for(auto i: a) cout << i << '\n';
return cout;
}
void yes(bool v) {cout << (v ? "yes\n" : "no\n");}
void YES(bool v) {cout << (v ? "YES\n" : "NO\n");}
void Yes(bool v) {cout << (v ? "Yes\n" : "No\n");}
TP bool cmax(o& x, o y) { return (x < y ? x = y, 1 : 0); }
TP bool cmin(o& x, o y) { return (x > y ? x = y, 1 : 0); }
TP void order(VT<o> &a) { sort(all(a)); a.resize(unique(all(a)) - a.begin());}
TP int get_id(VT<o> &a, const o& val) {return lower_bound(all(a), val) - a.begin();}
TP void sort(o &v) {sort(all(v));}
const int N = 303;
pii x[N], y[N];
db dis(int i, int j) {
db u = x[i].fi - y[j].fi, v = x[i].se - y[j].se;
return sqrtl(u * u + v * v);
}
const db eps = (db)1e-12, INF = 1e8;
int n;
db W[N][N];
int mat[N];
db Lx[N], Ly[N], slack[N];
bool S[N], T[N];
inline void tension(db &a, const db b) {
if(b < a) a = b;
}
inline bool match(int u) {
S[u] = true;
for(int v = 0; v < n; ++v) {
if(T[v]) continue;
db t = Lx[u] + Ly[v] - W[u][v];
if(fabs(t) < eps) {
T[v] = true;
if(mat[v] == -1 || match(mat[v])) {
mat[v] = u;
return true;
}
}else tension(slack[v], t);
}
return false;
}
inline void update() {
db d = INF;
for(int i = 0; i < n; ++i)
if(!T[i]) tension(d, slack[i]);
for(int i = 0; i < n; ++i) {
if(S[i]) Lx[i] -= d;
if(T[i]) Ly[i] += d;
}
}
inline void KM() {
for(int i = 0; i < n; ++i) {
Lx[i] = Ly[i] = 0; mat[i] = -1;
for(int j = 0; j < n; ++j) Lx[i] = max(Lx[i], W[i][j]);
}
for(int i = 0; i < n; ++i) {
fill(slack, slack + n, INF);
while(true) {
for(int j = 0; j < n; ++j) S[j] = T[j] = false;
if(match(i)) break;
else update();
}
}
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cout << fixed << setprecision(15);
qr(n);
rep(i, 0, n - 1) qr(x[i]);
rep(i, 0, n - 1) qr(y[i]);
rep(i, 0, n - 1) rep(j, 0, n - 1) W[i][j] = 20000 -dis(i, j);
KM();
if(count(mat, mat + n, -1)) cout << -1;
else {
VT<int> ans(n);
rep(i, 0, n - 1) ans[mat[i]] = i + 1;
cout << ans;
}
return 0;
}
Code2:
#include <bits/stdc++.h>
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define pll pair<ll, ll>
#define VT vector
#define VA valarray
#define pb push_back
#define SZ(a) ((int)a.size())
#define all(a) (a).begin(), (a).end()
#define TP template <class o>
#define TPP template <typename t1, typename t2>
#define rep(i, a, b) for (int i = a, i##_ = b; i <= i##_; i++)
#define REP(i, a, b) for (int i = b, i##_ = a; i >= i##_; i--)
#define FOR(i, n) rep(i, 1, n)
#define debug(x) cerr << #x << ' ' << '=' << ' ' << x << endl
#define db double
using namespace std;
TP void qr(o &x){cin>>x;}
TPP void qr(pair<t1, t2> &x) {qr(x.fi); qr(x.se);}
TP void pr1(o x) {cout << x << ' ';}
const int N = 300;
pii x[N], y[N];
int a[N], n;
db dis(int i, int j) {
db u = x[i].fi - y[j].fi, v = x[i].se - y[j].se;
return sqrtl(u * u + v * v);
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cout << fixed << setprecision(15);
qr(n);
rep(i, 0, n - 1) qr(x[i]);
rep(i, 0, n - 1) qr(y[i]);
rep(i, 0, n - 1) a[i] = i;
random_shuffle(a, a + n);
bool f;
do {
f = 0;
rep(i, 0, n - 1) rep(j, i + 1, n - 1)
if(dis(i, a[i]) + dis(j, a[j]) > dis(i, a[j]) + dis(j, a[i])) {
f = 1;
swap(a[i], a[j]);
}
} while(f);
rep(i, 0, n - 1) pr1(a[i] + 1);
return 0;
}