QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#183987 | #4901. Speike & Tom | hos_lyric# | 20 | 46ms | 25640kb | C++14 | 14.6kb | 2023-09-20 08:24:13 | 2024-07-04 02:05:13 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
template <class T> void bAdd(vector<T> &bit, int pos, const T &val) {
const int bitN = bit.size();
for (int x = pos; x < bitN; x |= x + 1) bit[x] += val;
}
template <class T> T bSum(const vector<T> &bit, int pos) {
T ret = 0;
for (int x = pos; x > 0; x &= x - 1) ret += bit[x - 1];
return ret;
}
template <class T> T bSum(const vector<T> &bit, int pos0, int pos1) {
return bSum(bit, pos1) - bSum(bit, pos0);
}
struct Hld {
int n, rt;
// needs to be tree
// vertex lists
// modified in build(rt) (parent removed, heavy child first)
vector<vector<int>> graph;
vector<int> sz, par, dep;
int zeit;
vector<int> dis, fin, sid;
// head vertex (minimum depth) in heavy path
vector<int> head;
Hld() : n(0), rt(-1), zeit(0) {}
explicit Hld(int n_) : n(n_), rt(-1), graph(n), zeit(0) {}
void ae(int u, int v) {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
graph[u].push_back(v);
graph[v].push_back(u);
}
void dfsSz(int u) {
sz[u] = 1;
for (const int v : graph[u]) {
auto it = std::find(graph[v].begin(), graph[v].end(), u);
if (it != graph[v].end()) graph[v].erase(it);
par[v] = u;
dep[v] = dep[u] + 1;
dfsSz(v);
sz[u] += sz[v];
}
}
void dfsHld(int u) {
dis[u] = zeit++;
const int deg = graph[u].size();
if (deg > 0) {
int vm = graph[u][0];
int jm = 0;
for (int j = 1; j < deg; ++j) {
const int v = graph[u][j];
if (sz[vm] < sz[v]) {
vm = v;
jm = j;
}
}
swap(graph[u][0], graph[u][jm]);
head[vm] = head[u];
dfsHld(vm);
for (int j = 1; j < deg; ++j) {
const int v = graph[u][j];
head[v] = v;
dfsHld(v);
}
}
fin[u] = zeit;
}
void build(int rt_) {
assert(0 <= rt_); assert(rt_ < n);
rt = rt_;
sz.assign(n, 0);
par.assign(n, -1);
dep.assign(n, -1);
dep[rt] = 0;
dfsSz(rt);
zeit = 0;
dis.assign(n, -1);
fin.assign(n, -1);
head.assign(n, -1);
head[rt] = rt;
dfsHld(rt);
assert(zeit == n);
sid.assign(n, -1);
for (int u = 0; u < n; ++u) sid[dis[u]] = u;
}
friend ostream &operator<<(ostream &os, const Hld &hld) {
const int maxDep = *max_element(hld.dep.begin(), hld.dep.end());
vector<string> ss(2 * maxDep + 1);
int pos = 0, maxPos = 0;
for (int j = 0; j < hld.n; ++j) {
const int u = hld.sid[j];
const int d = hld.dep[u];
if (hld.head[u] == u) {
if (j != 0) {
pos = maxPos + 1;
ss[2 * d - 1].resize(pos, '-');
ss[2 * d - 1] += '+';
}
} else {
ss[2 * d - 1].resize(pos, ' ');
ss[2 * d - 1] += '|';
}
ss[2 * d].resize(pos, ' ');
ss[2 * d] += std::to_string(u);
if (maxPos < static_cast<int>(ss[2 * d].size())) {
maxPos = ss[2 * d].size();
}
}
for (int d = 0; d <= 2 * maxDep; ++d) os << ss[d] << '\n';
return os;
}
bool contains(int u, int v) const {
return (dis[u] <= dis[v] && dis[v] < fin[u]);
}
int lca(int u, int v) const {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
for (; head[u] != head[v]; ) (dis[u] > dis[v]) ? (u = par[head[u]]) : (v = par[head[v]]);
return (dis[u] > dis[v]) ? v : u;
}
int jumpUp(int u, int d) const {
assert(0 <= u); assert(u < n);
assert(d >= 0);
if (dep[u] < d) return -1;
const int tar = dep[u] - d;
for (u = head[u]; ; u = head[par[u]]) {
if (dep[u] <= tar) return sid[dis[u] + (tar - dep[u])];
}
}
int jump(int u, int v, int d) const {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
assert(d >= 0);
const int l = lca(u, v);
const int du = dep[u] - dep[l], dv = dep[v] - dep[l];
if (d <= du) {
return jumpUp(u, d);
} else if (d <= du + dv) {
return jumpUp(v, du + dv - d);
} else {
return -1;
}
}
// [u, v) or [u, v]
template <class F> void doPathUp(int u, int v, bool inclusive, F f) const {
assert(contains(v, u));
for (; head[u] != head[v]; u = par[head[u]]) f(dis[head[u]], dis[u] + 1);
if (inclusive) {
f(dis[v], dis[u] + 1);
} else {
if (v != u) f(dis[v] + 1, dis[u] + 1);
}
}
// not path order, include lca(u, v) or not
template <class F> void doPath(int u, int v, bool inclusive, F f) const {
const int l = lca(u, v);
doPathUp(u, l, false, f);
doPathUp(v, l, inclusive, f);
}
// (vs, ps): compressed tree
// vs: DFS order (sorted by dis)
// vs[ps[x]]: the parent of vs[x]
// ids[vs[x]] = x, not set for non-tree vertex
vector<int> ids;
pair<vector<int>, vector<int>> compress(vector<int> us) {
// O(n) first time
ids.resize(n, -1);
std::sort(us.begin(), us.end(), [&](int u, int v) -> bool {
return (dis[u] < dis[v]);
});
us.erase(std::unique(us.begin(), us.end()), us.end());
int usLen = us.size();
assert(usLen >= 1);
for (int x = 1; x < usLen; ++x) us.push_back(lca(us[x - 1], us[x]));
std::sort(us.begin(), us.end(), [&](int u, int v) -> bool {
return (dis[u] < dis[v]);
});
us.erase(std::unique(us.begin(), us.end()), us.end());
usLen = us.size();
for (int x = 0; x < usLen; ++x) ids[us[x]] = x;
vector<int> ps(usLen, -1);
for (int x = 1; x < usLen; ++x) ps[x] = ids[lca(us[x - 1], us[x])];
return make_pair(us, ps);
}
};
////////////////////////////////////////////////////////////////////////////////
int N, M;
vector<int> A, B;
vector<vector<int>> G;
namespace brute {
// 0: first, nigeru; 1: second, ou
int win[2][2010][2010];
int deg[2][2010][2010];
Int run() {
vector<int> degTree(N, 0);
for (int i = 0; i < N - 1; ++i) {
++degTree[A[i]];
++degTree[B[i]];
}
memset(win, ~0, sizeof(win));
memset(deg, 0, sizeof(deg));
queue<pair<int, pair<int, int>>> que;
for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) {
if (u == v) {
for (int t = 0; t < 2; ++t) {
win[t][u][v] = t;
que.emplace(t, make_pair(u, v));
}
} else {
deg[0][u][v] = 1 + (int)G[u].size();
deg[1][u][v] = 1 + degTree[v];
}
}
for (; !que.empty(); ) {
const int t = que.front().first;
const int u = que.front().second.first;
const int v = que.front().second.second;
que.pop();
auto reach = [&](int tt, int uu, int vv) -> void {
if (!~win[tt][uu][vv]) {
if (win[t][u][v]) {
if (!--deg[tt][uu][vv]) {
win[tt][uu][vv] = 0;
que.emplace(tt, make_pair(uu, vv));
}
} else {
win[tt][uu][vv] = 1;
que.emplace(tt, make_pair(uu, vv));
}
}
};
if (t) {
// reverse nigeru
reach(0, u, v);
for (const int i : G[u]) {
reach(0, A[i] ^ B[i] ^ u, v);
}
} else {
// reverse ou
reach(1, u, v);
for (const int i : G[v]) if (i < N - 1) {
reach(1, u, A[i] ^ B[i] ^ v);
}
}
}
// for(int t=0;t<2;++t)for(int u=0;u<N;++u){cerr<<"win["<<t<<"]["<<u<<"] = ";pv(win[t][u],win[t][u]+N);}
Int ans = 0;
for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) if (u != v) {
if (win[0][u][v]) {
++ans;
}
}
return ans;
}
} // brute
namespace one {
vector<int> par;
void dfs(int u, int p) {
par[u] = p;
for (const int i : G[u]) if (i < N - 1) {
const int v = A[i] ^ B[i] ^ u;
if (p != v) {
dfs(v, u);
}
}
}
vector<int> on;
vector<vector<int>> dss;
void DFS(int k, int u, int p, int d) {
dss[k].push_back(d);
for (const int i : G[u]) if (i < N - 1) {
const int v = A[i] ^ B[i] ^ u;
if (p != v && !on[v]) {
DFS(k, v, u, d + 1);
}
}
}
Int run() {
const int s = A[N - 1];
const int t = B[N - 1];
par.assign(N, -1);
dfs(s, -1);
vector<int> path;
for (int u = t; ~u; u = par[u]) {
path.push_back(u);
}
reverse(path.begin(), path.end());
const int len = (int)path.size() - 1;
// cerr<<"path = "<<path<<endl;
Int ans = 0;
if (len >= 3) {
on.assign(N, 0);
for (int k = 0; k <= len; ++k) {
on[path[k]] = 1;
}
dss.assign(len + 1, {});
for (int k = 0; k <= len; ++k) {
DFS(k, path[k], -1, 0);
}
// go to s
{
vector<int> bit(N, 0);
for (int k = 0; k <= len; ++k) {
for (const int d : dss[k]) bAdd(bit, k + d, +1);
for (const int d : dss[k]) ans += bSum(bit, k + d);
}
}
// go to t
{
vector<int> bit(N, 0);
for (int k = len; k >= 0; --k) {
for (const int d : dss[k]) ans += bSum(bit, (len - k) + d);
for (const int d : dss[k]) bAdd(bit, (len - k) + d, +1);
}
}
}
return ans;
}
} // one
namespace fast {
Int ans;
Hld hld;
vector<vector<int>> skip;
vector<int> on;
vector<vector<int>> graph;
vector<int> sz, del;
void dfsSz(int u, int p) {
sz[u] = 1;
for (const int v : graph[u]) if (p != v) {
dfsSz(v, u);
sz[u] += sz[v];
}
}
string dfsString(int u, int p) {
ostringstream oss;
oss << "[" << u;
for (const int v : graph[u]) if (!del[v] && p != v) {
oss << " " << dfsString(v, u);
}
oss << "]";
return oss.str();
}
vector<int> costs;
vector<vector<int>> css[2];
void sub(int j, int u, int p, int p2, int d, int e) {
for (const int v : skip[u]) {
if (p2 == v) {
costs[u] = costs[p2] + 1;
} else if (on[v] == 1 && j != (int)css[0].size() - 1) {
costs[u] = 0;
}
}
css[0][j].push_back(costs[u] - d);
css[1][j].push_back(e + d);
for (const int i : G[u]) if (i < N - 1) {
const int v = A[i] ^ B[i] ^ u;
if (!on[v] && p != v) {
costs[v] = costs[u] + 1;
sub(j, v, u, p, d, e + 1);
}
}
}
void dfs(int j, int u, int p, int d) {
costs[u] = 0;
on[p] = 2;
sub(j, u, -1, -1, d, 0);
on[p] = 1;
for (const int v : graph[u]) if (!del[v] && p != v) {
dfs(j, v, u, d + 1);
}
}
void solveSubtree(int depth, int r) {
#ifdef LOCAL
cerr << string(2 * depth, ' ') << "solveSubtree " << dfsString(r, -1) << endl;
#endif
vector<int> vs;
for (const int v : graph[r]) if (!del[v]) {
vs.push_back(v);
}
const int len = vs.size();
for (int h = 0; h < 2; ++h) {
css[h].assign(len + 1, {});
}
for (int j = 0; j < len; ++j) {
dfs(j, vs[j], r, 1);
}
costs[r] = 0;
sub(len, r, -1, -1, 0, 0);
// cerr<<string(2*depth,' ')<<"vs = "<<vs<<", costs = "<<costs<<", css = ";pv(css,css+2);
for (int h = 0; h < 2; ++h) {
for (int j = 0; j < len; ++j) {
css[h][len].insert(css[h][len].end(), css[h][j].begin(), css[h][j].end());
}
for (int j = 0; j <= len; ++j) {
sort(css[h][j].begin(), css[h][j].end());
}
}
Int sum = 0;
for (int j = 0; j <= len; ++j) {
int pos0 = 0;
for (int pos1 = 0; pos1 < (int)css[1][j].size(); ++pos1) {
for (; pos0 < (int)css[0][j].size() && css[0][j][pos0] < css[1][j][pos1]; ++pos0) {}
sum += ((j < len) ? -1 : +1) * pos0;
}
}
// cerr<<string(2*depth,' ')<<"sum = "<<sum<<endl;
ans += sum;
}
void solveRec(int depth, int u) {
for (; ; ) {
int vm = -1;
for (const int v : graph[u]) if (!del[v]) {
if (!~vm || sz[vm] < sz[v]) {
vm = v;
}
}
if (!~vm || 2 * sz[vm] <= sz[u]) {
solveSubtree(depth, u);
del[u] = 1;
for (const int v : graph[u]) if (!del[v]) {
solveRec(depth + 1, v);
}
break;
} else {
sz[u] -= sz[vm];
sz[vm] += sz[u];
u = vm;
}
}
}
void centroidDecomp(int r) {
sz.assign(N, 0);
dfsSz(r, -1);
del.assign(N, 0);
costs.assign(N, 0);
solveRec(0, r);
}
Int run() {
ans = 0;
hld = Hld(N);
for (int i = 0; i < N - 1; ++i) {
hld.ae(A[i], B[i]);
}
hld.build(0);
vector<int> tar(N, 0);
skip.assign(N, {});
for (int i = N - 1; i < M; ++i) {
const int d = hld.dep[A[i]] + hld.dep[B[i]] - 2 * hld.dep[hld.lca(A[i], B[i])];
if (d >= 3) {
tar[A[i]] = tar[B[i]] = 1;
} else if (d == 2) {
skip[A[i]].push_back(B[i]);
skip[B[i]].push_back(A[i]);
}
}
on.assign(N, 0);
for (int j = N; --j >= 1; ) {
const int u = hld.sid[j];
tar[hld.par[u]] += tar[u];
}
for (int j = N; --j >= 1; ) {
const int u = hld.sid[j];
if (0 < tar[u] && tar[u] < tar[0]) {
on[hld.par[u]] = on[u] = 1;
}
}
// cerr<<"on = "<<on<<endl;
int r = -1;
for (int u = 0; u < N; ++u) if (on[u]) {
r = u;
break;
}
if (~r) {
graph.assign(N, {});
for (int i = 0; i < N - 1; ++i) if (on[A[i]] && on[B[i]]) {
graph[A[i]].push_back(B[i]);
graph[B[i]].push_back(A[i]);
}
centroidDecomp(r);
}
return ans;
}
} // fast
int main() {
for (; ~scanf("%d%d", &N, &M); ) {
M += (N - 1);
A.resize(M);
B.resize(M);
for (int i = 0; i < M; ++i) {
scanf("%d%d", &A[i], &B[i]);
--A[i];
--B[i];
}
G.assign(N, {});
for (int i = 0; i < M; ++i) {
G[A[i]].push_back(i);
G[B[i]].push_back(i);
}
const Int ans = fast::run();
printf("%lld\n", ans);
#ifdef LOCAL
const Int brt=brute::run();
cerr<<"brt = "<<brt<<endl;
// assert(brt==ans);
#endif
}
return 0;
}
详细
Subtask #1:
score: 10
Accepted
Test #1:
score: 10
Accepted
time: 0ms
memory: 3828kb
input:
20 3 1 2 1 3 3 4 4 5 1 6 6 7 1 8 5 9 8 10 5 11 7 12 11 13 12 14 11 15 4 16 7 17 2 18 1 19 3 20 8 20 12 4 10 1
output:
307
result:
ok 1 number(s): "307"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3804kb
input:
20 4 1 2 2 3 1 4 3 5 4 6 3 7 4 8 3 9 2 10 8 11 8 12 7 13 8 14 14 15 4 16 1 17 4 18 6 19 19 20 9 13 14 2 14 13 15 6
output:
343
result:
ok 1 number(s): "343"
Test #3:
score: 0
Accepted
time: 0ms
memory: 3828kb
input:
19 4 1 2 1 3 1 4 4 5 4 6 3 7 7 8 6 9 4 10 2 11 6 12 7 13 1 14 13 15 6 16 12 17 3 18 3 19 8 12 4 6 18 5 11 9
output:
314
result:
ok 1 number(s): "314"
Test #4:
score: 0
Accepted
time: 0ms
memory: 3808kb
input:
20 3 1 2 2 3 3 4 4 5 1 6 2 7 1 8 3 9 9 10 5 11 8 12 10 13 12 14 8 15 9 16 11 17 5 18 17 19 19 20 9 19 10 15 18 15
output:
358
result:
ok 1 number(s): "358"
Test #5:
score: 0
Accepted
time: 0ms
memory: 4096kb
input:
20 6 1 2 1 3 3 4 4 5 1 6 6 7 5 8 4 9 7 10 6 11 10 12 6 13 10 14 1 15 15 16 8 17 17 18 15 19 18 20 17 2 16 3 10 1 8 7 13 5 19 7
output:
361
result:
ok 1 number(s): "361"
Test #6:
score: 0
Accepted
time: 0ms
memory: 4104kb
input:
20 8 1 2 2 3 1 4 1 5 1 6 4 7 2 8 4 9 2 10 1 11 11 12 2 13 10 14 1 15 6 16 16 17 11 18 10 19 3 20 2 6 6 7 1 18 18 13 1 20 3 12 8 4 7 1
output:
324
result:
ok 1 number(s): "324"
Subtask #2:
score: 0
Wrong Answer
Dependency #1:
100%
Accepted
Test #7:
score: 0
Wrong Answer
time: 1ms
memory: 3872kb
input:
300 26 1 2 1 3 2 4 4 5 3 6 6 7 5 8 2 9 1 10 10 11 6 12 8 13 6 14 10 15 6 16 4 17 9 18 10 19 5 20 18 21 6 22 10 23 18 24 1 25 19 26 17 27 8 28 10 29 25 30 16 31 27 32 13 33 4 34 5 35 12 36 9 37 15 38 32 39 29 40 11 41 5 42 28 43 1 44 25 45 27 46 3 47 34 48 27 49 9 50 39 51 20 52 48 53 10 54 35 55 23 ...
output:
86688
result:
wrong answer 1st numbers differ - expected: '86687', found: '86688'
Subtask #3:
score: 0
Skipped
Dependency #2:
0%
Subtask #4:
score: 0
Skipped
Dependency #3:
0%
Subtask #5:
score: 10
Accepted
Test #29:
score: 10
Accepted
time: 28ms
memory: 21064kb
input:
98765 1 2 1 3 1 4 2 5 2 6 5 7 4 8 6 9 7 10 7 11 6 12 1 13 11 14 13 15 7 16 6 17 14 18 4 19 13 20 14 21 11 22 21 23 1 24 13 25 7 26 16 27 8 28 21 29 20 30 10 31 12 32 10 33 7 34 31 35 29 36 29 37 30 38 34 39 38 40 14 41 40 42 26 43 33 44 1 45 44 46 25 47 14 48 2 49 30 50 26 51 46 52 34 53 32 54 31 55...
output:
0
result:
ok 1 number(s): "0"
Test #30:
score: 0
Accepted
time: 23ms
memory: 21096kb
input:
99824 1 2 1 3 1 4 1 5 1 6 2 7 2 8 1 9 3 10 9 11 4 12 6 13 6 14 2 15 3 16 9 17 13 18 15 19 4 20 13 21 12 22 15 23 5 24 16 25 17 26 9 27 26 28 18 29 8 30 23 31 5 32 31 33 28 34 5 35 11 36 20 37 6 38 36 39 35 40 4 41 11 42 10 43 12 44 28 45 15 46 38 47 9 48 36 49 16 50 45 51 49 52 44 53 6 54 12 55 5 56...
output:
0
result:
ok 1 number(s): "0"
Test #31:
score: 0
Accepted
time: 46ms
memory: 19024kb
input:
67765 1 2 1 3 2 4 1 5 2 6 2 7 3 8 4 9 3 10 5 11 6 12 4 13 7 14 13 15 11 16 11 17 3 18 8 19 2 20 13 21 19 22 7 23 14 24 7 25 6 26 21 27 1 28 1 29 2 30 16 31 9 32 31 33 26 34 1 35 21 36 10 37 32 38 16 39 38 40 10 41 20 42 23 43 8 44 10 45 14 46 42 47 12 48 17 49 45 50 28 51 42 52 49 53 44 54 9 55 8 56...
output:
2254349415
result:
ok 1 number(s): "2254349415"
Test #32:
score: 0
Accepted
time: 39ms
memory: 25640kb
input:
100000 1 2 1 3 1 4 3 5 4 6 2 7 1 8 2 9 5 10 3 11 9 12 10 13 3 14 12 15 13 16 11 17 8 18 14 19 8 20 16 21 7 22 18 23 19 24 21 25 5 26 10 27 22 28 21 29 8 30 17 31 10 32 30 33 7 34 22 35 13 36 30 37 8 38 20 39 23 40 11 41 17 42 35 43 2 44 13 45 17 46 37 47 4 48 37 49 11 50 26 51 45 52 45 53 18 54 44 5...
output:
4706707961
result:
ok 1 number(s): "4706707961"
Subtask #6:
score: 0
Skipped
Dependency #1:
100%
Accepted
Dependency #2:
0%