QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#165373 | #6738. Cover | mendicillin2# | WA | 569ms | 27288kb | C++17 | 7.1kb | 2023-09-05 17:46:45 | 2023-09-05 17:46:45 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
template <class T> int sz(T&& a) { return int(size(forward<T>(a))); }
template <class T> using vc = vector<T>;
template <class T> using vvc = vc<vc<T>>;
using ll = int64_t;
using vi = vc<int>;
mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
template <class F>
struct ycr {
F f;
template <class T> explicit ycr(T&& f_) : f(forward<T>(f_)) {}
template <class... Args> decltype(auto) operator()(Args&&... args) {
return f(ref(*this), forward<Args>(args)...);
}
};
template <class F> decltype(auto) yc(F&& f) {
return ycr<decay_t<F>>(forward<F>(f));
}
void wassert(bool b) {
if (!b) {
cout << "nmsl" << endl;
exit(0);
}
}
struct GC {
char buf[1<<16];
size_t s = 0, e = 0;
char operator()() {
if (s >= e) {
buf[0] = 0;
s = 0;
e = fread(buf, 1, sizeof(buf), stdin);
}
return buf[s++];
}
} gc;
int scan_int() {
char c;
while ((c = gc()) < 40);
if (c == '-') return -scan_int();
int a = c - '0';
while (isdigit(c = gc())) a = a * 10 + c - '0';
return a;
}
template <class T> void setmax(T& a, const T& b) {
if (a < b) a = b;
}
struct hldecomp {
int n;
vi ord;
vc<array<int, 2>> idx;
vc<pair<int, int>> heavy;
vvc<int> ch;
hldecomp(const vi& par) : n(sz(par)), ord(n), idx(n), heavy(n) {
ch.resize(n);
for (int i = 0; i < n; i++) {
if (par[i] != -1) {
ch[par[i]].push_back(i);
}
}
vi s(n);
int nidx = 0;
for (int i = 0; i < n; i++) {
if (par[i] != -1) continue;
yc([&](auto self, int v) -> void {
s[v] = 1;
for (int w : ch[v]) {
self(w);
s[v] += s[w];
}
if (!ch[v].empty()) {
auto mit = max_element(ch[v].begin(), ch[v].end(), [&](int a, int b) {
return s[a] < s[b];
});
swap(*ch[v].begin(), *mit);
}
})(i);
yc([&](auto self, int v, bool rt = true) -> void {
ord[idx[v][0] = nidx++] = v;
if (rt) {
heavy[idx[v][0]] = {par[v] == -1 ? -1 : idx[par[v]][0], 1};
} else {
assert(idx[par[v]][0] == idx[v][0]-1);
heavy[idx[v][0]] = heavy[idx[v][0]-1];
heavy[idx[v][0]].second++;
}
bool crt = false;
for (int w : ch[v]) {
self(w, crt);
crt = true;
}
idx[v][1] = nidx;
})(i);
}
assert(n == nidx);
}
int lca(int a, int b) {
a = idx[a][0], b = idx[b][0];
while (true) {
if (a > b) swap(a, b);
assert(a <= b);
if (a > b - heavy[b].second) {
return ord[a];
}
b = heavy[b].first;
if (b == -1) return -1;
}
}
bool in_subtree(int a, int p) const {
return idx[p][0] <= idx[a][0] &&
idx[a][1] <= idx[p][1];
}
};
template <class T> struct FT {
vc<T> d;
int s;
FT(int n) { init(n); }
void init(int n) {
d.clear();
d.resize(s = n);
}
void add(int i, T v) {
for (; i < s; i |= i+1) d[i] += v;
}
T get(int i) {
T res = 0;
for (; i; i &= i-1) res += d[i-1];
return res;
}
};
int main() {
//ios_base::sync_with_stdio(false), cin.tie(nullptr);
int N, M, K;
N = scan_int();
M = scan_int();
K = scan_int();
vector<vector<int>> adj(N);
for (int e = 0; e < N-1; e++) {
int a = scan_int()-1;
int b = scan_int()-1;
adj[a].push_back(b);
adj[b].push_back(a);
}
vector<int> par(N);
{
yc([&](auto self, int cur, int prv) -> void {
par[cur] = prv;
for (int nxt : adj[cur]) {
if (nxt == prv) continue;
self(nxt, cur);
}
})(0, -1);
}
hldecomp hld(par);
const auto& tree = hld.ch;
struct P {
int a, b, w;
};
vector<vector<P>> paths(N);
for (int j = 0; j < M; j++) {
int a = scan_int()-1;
int b = scan_int()-1;
int w = scan_int();
int c = hld.lca(a, b);
paths[c].push_back(P{a, b, w});
}
vector<ll> ans(N);
FT<ll> ft_sum(N);
FT<ll> ft_sum_ch(N);
vector<ll> sum_ch(N);
vector<ll> cur_dp(1 << K);
vector<ll> cur_set_sum(1 << K);
yc([&](auto self, int cur) -> void {
for (int nxt : tree[cur]) {
self(nxt);
}
const int num_ch = int(tree[cur].size());
assert(num_ch <= K);
vector<ll> best(num_ch);
vector<vector<ll>> best2(num_ch, vector<ll>(num_ch));
auto update_sum = [&](int i, ll x) -> void {
assert(x >= 0);
assert(hld.idx[i][0] < hld.idx[i][1]);
ft_sum.add(hld.idx[i][0], x);
ft_sum.add(hld.idx[i][1], -x);
};
auto update_sum_ch = [&](int i, ll x) -> void {
ft_sum_ch.add(hld.idx[i][0], x);
ft_sum_ch.add(hld.idx[i][1], -x);
};
auto get_sum = [&](int i) -> ll {
const int idx = hld.idx[i][0];
return ft_sum.get(idx+1);
};
auto get_sum_ch = [&](int i) -> ll {
const int idx = hld.idx[i][0];
return ft_sum_ch.get(idx+1);
};
auto get_which_ch = [&](int i) -> int {
for (int c = 0; c < num_ch; c++) {
if (hld.in_subtree(i, tree[cur][c])) return c;
}
assert(false);
};
auto get_val = [&](int i, int c) -> ll {
// Line
//return ans[i];
ll res = get_sum_ch(i) - get_sum(i) - sum_ch[i] + ans[i];
res += ans[tree[cur][c]];
//if (i != tree[cur][c]) res += ans[tree[cur][c]];
//assert(res == ans[i]);
return res;
/*
cerr << "sum_ch=" << get_sum_ch(i) << endl;
cerr << "sum=" << get_sum(i) << endl;
cerr << "get(" << cur << ", " << i << ") = " << res << endl;
return res;
*/
/*
ll res = ans[i];
if (i == tree[cur][c]) return res;
for (int prv = i, v = par[i]; ; prv = v, v = par[v]) {
assert(sum_ch[v] == ans[prv]);
res += sum_ch[v];
res -= ans[prv];
if (v == tree[cur][c]) break;
}
assert(res == ans[i]);
return res;
*/
};
for (auto [a, b, w] : paths[cur]) {
if (b == cur) {
swap(a, b);
}
if (a == cur) {
assert(b != cur);
const int b_ch = get_which_ch(b);
//assert(get_val(b) == ans[b]);
const ll val = get_val(b, b_ch) + w;
//assert(val <= ll(1e14));
setmax(best[b_ch], val);
} else {
int a_ch = get_which_ch(a);
int b_ch = get_which_ch(b);
//assert(get_val(a) == ans[a]);
//assert(get_val(b) == ans[b]);
const ll val = get_val(a, a_ch) + get_val(b, b_ch) + w;
//assert(val <= ll(1e14));
if (a_ch > b_ch) swap(a_ch, b_ch);
assert(a_ch < b_ch);
setmax(best2[a_ch][b_ch], val);
}
}
for (int m = 1; m < (1 << num_ch); m++) {
const int i = __builtin_ctz(m);
cur_dp[m] = cur_dp[m - (1 << i)] + best[i];
for (int j = i+1; j < num_ch; j++) {
if (m & (1 << j)) {
setmax(cur_dp[m], cur_dp[m - (1 << i) - (1 << j)] + best2[i][j]);
}
}
}
for (int m = 1; m < (1 << num_ch); m++) {
const int i = __builtin_ctz(m);
cur_set_sum[m] = cur_set_sum[m - (1 << i)] + ans[tree[cur][i]];
}
for (int m = 0, c = (1 << num_ch)-1; m < (1 << num_ch); m++, c--) {
//assert(ans[cur] <= ll(1e14));
setmax(ans[cur], cur_dp[m] + cur_set_sum[c]);
}
//cerr << "ans(" << cur << ")=" << ans[cur] << endl;
for (int nxt : tree[cur]) {
sum_ch[cur] += ans[nxt];
}
update_sum(cur, ans[cur]);
update_sum_ch(cur, sum_ch[cur]);
assert(get_sum(cur) == ans[cur]);
})(0);
cout << ans[0] << '\n';
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3552kb
input:
5 7 3 1 2 1 3 2 4 2 5 3 2 8 5 4 10 3 1 2 1 2 7 2 1 2 1 2 1 5 2 3
output:
19
result:
ok 1 number(s): "19"
Test #2:
score: -100
Wrong Answer
time: 569ms
memory: 27288kb
input:
100000 500000 12 2 1 3 2 4 2 5 2 6 5 7 2 8 5 9 3 10 2 11 2 12 5 13 1 14 1 15 1 16 1 17 1 18 1 19 1 20 1 21 1 22 1 23 1 24 12 25 2 26 2 27 2 28 2 29 2 30 15 31 30 32 23 33 26 34 22 35 30 36 26 37 3 38 3 39 3 40 3 41 3 42 3 43 3 44 3 45 3 46 3 47 20 48 21 49 4 50 4 51 4 52 4 53 4 54 4 55 4 56 4 57 4 5...
output:
477136968048
result:
wrong answer 1st numbers differ - expected: '660925834533', found: '477136968048'