結果
問題 | No.2892 Lime and Karin |
ユーザー | fuppy_kyopro |
提出日時 | 2024-09-16 19:21:04 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 142 ms / 8,000 ms |
コード長 | 11,589 bytes |
コンパイル時間 | 2,878 ms |
コンパイル使用メモリ | 220,668 KB |
実行使用メモリ | 36,616 KB |
最終ジャッジ日時 | 2024-09-16 19:21:15 |
合計ジャッジ時間 | 10,410 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge6 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 2 ms
5,376 KB |
testcase_13 | AC | 2 ms
5,376 KB |
testcase_14 | AC | 60 ms
13,184 KB |
testcase_15 | AC | 56 ms
12,544 KB |
testcase_16 | AC | 95 ms
18,304 KB |
testcase_17 | AC | 22 ms
7,296 KB |
testcase_18 | AC | 94 ms
18,304 KB |
testcase_19 | AC | 135 ms
23,296 KB |
testcase_20 | AC | 8 ms
5,376 KB |
testcase_21 | AC | 72 ms
14,848 KB |
testcase_22 | AC | 90 ms
17,664 KB |
testcase_23 | AC | 38 ms
9,728 KB |
testcase_24 | AC | 138 ms
23,680 KB |
testcase_25 | AC | 137 ms
23,532 KB |
testcase_26 | AC | 142 ms
23,552 KB |
testcase_27 | AC | 138 ms
23,680 KB |
testcase_28 | AC | 139 ms
23,680 KB |
testcase_29 | AC | 133 ms
23,552 KB |
testcase_30 | AC | 140 ms
23,552 KB |
testcase_31 | AC | 134 ms
23,680 KB |
testcase_32 | AC | 134 ms
23,552 KB |
testcase_33 | AC | 135 ms
23,680 KB |
testcase_34 | AC | 65 ms
24,848 KB |
testcase_35 | AC | 63 ms
24,848 KB |
testcase_36 | AC | 65 ms
24,828 KB |
testcase_37 | AC | 65 ms
24,788 KB |
testcase_38 | AC | 66 ms
24,852 KB |
testcase_39 | AC | 121 ms
29,128 KB |
testcase_40 | AC | 123 ms
35,892 KB |
testcase_41 | AC | 118 ms
30,360 KB |
testcase_42 | AC | 128 ms
36,616 KB |
testcase_43 | AC | 119 ms
32,324 KB |
testcase_44 | AC | 46 ms
11,264 KB |
testcase_45 | AC | 116 ms
21,376 KB |
testcase_46 | AC | 53 ms
12,416 KB |
testcase_47 | AC | 74 ms
15,488 KB |
testcase_48 | AC | 32 ms
8,704 KB |
testcase_49 | AC | 90 ms
17,280 KB |
testcase_50 | AC | 98 ms
24,336 KB |
testcase_51 | AC | 94 ms
24,200 KB |
testcase_52 | AC | 99 ms
24,304 KB |
testcase_53 | AC | 99 ms
24,320 KB |
testcase_54 | AC | 98 ms
24,320 KB |
ソースコード
/* #pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") //*/ // #include <atcoder/all> #include <bits/stdc++.h> using namespace std; // using namespace atcoder; // #define _GLIBCXX_DEBUG #define DEBUG(x) cerr << #x << ": " << x << endl; #define DEBUG_VEC(v) \ cerr << #v << ":"; \ for (int iiiiiiii = 0; iiiiiiii < v.size(); iiiiiiii++) \ cerr << " " << v[iiiiiiii]; \ cerr << endl; #define DEBUG_MAT(v) \ cerr << #v << endl; \ for (int iv = 0; iv < v.size(); iv++) { \ for (int jv = 0; jv < v[iv].size(); jv++) { \ cerr << v[iv][jv] << " "; \ } \ cerr << endl; \ } typedef long long ll; // #define int ll #define vi vector<int> #define vl vector<ll> #define vii vector<vector<int>> #define vll vector<vector<ll>> #define pii pair<int, int> #define pis pair<int, string> #define psi pair<string, int> #define pll pair<ll, ll> template <class S, class T> pair<S, T> operator+(const pair<S, T> &s, const pair<S, T> &t) { return pair<S, T>(s.first + t.first, s.second + t.second); } template <class S, class T> pair<S, T> operator-(const pair<S, T> &s, const pair<S, T> &t) { return pair<S, T>(s.first - t.first, s.second - t.second); } template <class S, class T> ostream &operator<<(ostream &os, pair<S, T> p) { os << "(" << p.first << ", " << p.second << ")"; return os; } #define rep(i, n) for (int i = 0; i < (int)(n); i++) #define rep1(i, n) for (int i = 1; i <= (int)(n); i++) #define rrep(i, n) for (int i = (int)(n) - 1; i >= 0; i--) #define rrep1(i, n) for (int i = (int)(n); i > 0; i--) #define REP(i, a, b) for (int i = a; i < b; i++) #define in(x, a, b) (a <= x && x < b) #define all(c) c.begin(), c.end() void YES(bool t = true) { cout << (t ? "YES" : "NO") << endl; } void Yes(bool t = true) { cout << (t ? "Yes" : "No") << endl; } void yes(bool t = true) { cout << (t ? "yes" : "no") << endl; } void NO(bool t = true) { cout << (t ? "NO" : "YES") << endl; } void No(bool t = true) { cout << (t ? "No" : "Yes") << endl; } void no(bool t = true) { cout << (t ? "no" : "yes") << endl; } template <class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return 1; } return 0; } template <class T> bool chmin(T &a, const T &b) { if (a > b) { a = b; return 1; } return 0; } template <class T, class U> T ceil_div(T a, U b) { return (a + b - 1) / b; } template <class T> T safe_mul(T a, T b) { if (a == 0 || b == 0) return 0; if (numeric_limits<T>::max() / a < b) return numeric_limits<T>::max(); return a * b; } #define UNIQUE(v) v.erase(std::unique(v.begin(), v.end()), v.end()); const ll inf = 1000000001; const ll INF = (ll)1e18 + 1; const long double pi = 3.1415926535897932384626433832795028841971L; int popcount(ll t) { return __builtin_popcountll(t); } vector<int> gen_perm(int n) { vector<int> ret(n); iota(all(ret), 0); return ret; } // int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1}; // int dx2[8] = { 1,1,0,-1,-1,-1,0,1 }, dy2[8] = { 0,1,1,1,0,-1,-1,-1 }; vi dx = {0, 0, -1, 1}, dy = {-1, 1, 0, 0}; vi dx2 = {1, 1, 0, -1, -1, -1, 0, 1}, dy2 = {0, 1, 1, 1, 0, -1, -1, -1}; struct Setup_io { Setup_io() { ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0); cout << fixed << setprecision(25); cerr << fixed << setprecision(25); } } setup_io; // constexpr ll MOD = 1000000007; constexpr ll MOD = 998244353; // #define mp make_pair struct DSUOnTree { // https://nyaannyaan.github.io/library/tree/dsu-on-tree.hpp.html // https://codeforces.com/blog/entry/44351 vector<vector<int>> G; int n; // 頂点 u の部分木は ord の [from[u], to[u]) の範囲に入っている vector<int> sub, ord, from, to; int root; int dfs_sub(int now, int par) { sub[now] = 1; if (G[now].size() >= 2 && G[now][0] == par) { // 最初の子は Big Child になるようにする swap(G[now][0], G[now][1]); } for (int i = 0; i < G[now].size(); i++) { int to = G[now][i]; if (to == par) continue; sub[now] += dfs_sub(to, now); if (i != 0 && sub[G[now][0]] < sub[to]) { swap(G[now][0], G[now][i]); } } return sub[now]; } void dfs_ord(int now, int par, int &idx) { from[now] = idx; ord[idx++] = now; for (int to : G[now]) { if (to == par) continue; dfs_ord(to, now, idx); } to[now] = idx; } public: DSUOnTree(vector<vector<int>> G, int root) : G(G), n(G.size()), root(root) { sub.resize(n); from.resize(n); to.resize(n); ord.reserve(n); dfs_sub(root, -1); int idx = 0; dfs_ord(root, -1, idx); } using F = function<void(int)>; void run(F update, F query, F clear) { // 各関数を通じて、外部に用意した配列やセグ木にアクセスする想定 // update(u): 頂点 u 単体に関して値を更新する // query(u): 頂点 u が属する部分木に関しての更新が終わった状態でクエリを処理する // clear(u): 頂点 u 単体に関しての更新を解除する // verify: https://judge.yosupo.jp/submission/235963 auto dfs = [&](auto &&self, int now, int par, bool keep) -> void { // dfs Small Child for (int i = 1; i < G[now].size(); i++) { if (G[now][i] == par) continue; self(self, G[now][i], now, false); } // dfs Big Child if (sub[now] > 1) { self(self, G[now][0], now, true); } // update Small Child if (sub[now] > 1) { int bc = G[now][0]; for (int i = to[bc]; i < to[now]; i++) { update(ord[i]); } } update(now); query(now); if (!keep) { for (int i = from[now]; i < to[now]; i++) { clear(ord[i]); } } return; }; dfs(dfs, root, -1, true); } using F2 = function<void(int, int)>; void run_every_pair(F update, F query_root, F2 query_light, F clear) { // 各関数を通じて、外部に用意した配列やセグ木にアクセスする想定。 // 全ての異なる頂点ペアに関するクエリを処理する。同じ頂点ペアに関するクエリがある場合は別途処理する必要がある。 // update(u): 頂点 u 単体に関して値を更新する // query_root(u): 頂点 u を根として追加する時に、u とその子孫に関するクエリを処理する。 // query_light(r, u): 頂点 r が根の時に頂点 u を Small Child として追加する時に、 // u と「r の Big Child, および r の処理済みの Small Child」に関するクエリを処理する。 // u と r に関するクエリは query_root で処理されるので、ここでは扱わない // clear(u): 頂点 u 単体に関しての更新を解除する auto dfs = [&](auto &&self, int now, int par, bool keep) -> void { // dfs Small Child for (int i = 1; i < G[now].size(); i++) { if (G[now][i] == par) continue; self(self, G[now][i], now, false); } // dfs Big Child if (sub[now] > 1) { self(self, G[now][0], now, true); } // update Small Child if (sub[now] > 1) { for (int i = 1; i < G[now].size(); i++) { if (G[now][i] == par) continue; int ch = G[now][i]; // Big Child とすでに処理済みの Small Child に関するクエリを処理 for (int u = from[ch]; u < to[ch]; u++) { query_light(now, ord[u]); } for (int u = from[ch]; u < to[ch]; u++) { update(ord[u]); } } } // 根と子孫の間のクエリを処理 query_root(now); update(now); if (!keep) { for (int i = from[now]; i < to[now]; i++) { clear(ord[i]); } } return; }; dfs(dfs, root, -1, true); } }; class Bit { public: int n; vl bit; // 0-index Bit(int _n) { n = _n; bit.resize(n); } // [0, i) ll sum(int i) { ll s = 0; while (i > 0) { s += bit[i - 1]; i -= i & -i; } return s; } // [l, r) ll sum(int l, int r) { if (l >= r) return 0; return sum(r) - sum(l); } void add(int i, ll x) { i++; while (i <= n) { bit[i - 1] += x; i += i & -i; } } ll min_xth(int x) { // なぜか 1-indexed // x = 0 の時は必ず 0 が返っていそう int left = -1, right = n; while (left + 1 < right) { int mid = (left + right) / 2; int temp = sum(mid + 1); if (temp < x) { left = mid; } else { right = mid; } } return right; } ll bubble(vi p) { int n = p.size(); ll ans = 0; for (int j = 0; j < n; j++) { ans += (j - sum(p[j] + 1)); add(p[j], 1); } return ans; } }; signed main() { int n; cin >> n; vii G(n); rep(i, n - 1) { int u, v; cin >> u >> v; u--; v--; G[u].push_back(v); G[v].push_back(u); } string s; cin >> s; vi a(n); rep(i, n) { if (s[i] == '1') a[i] = 1; else a[i] = -1; } vi rui(n); auto dfs_rui = [&](auto &&f, int now, int par, int d) -> void { rui[now] = d + a[now]; for (int to : G[now]) { if (to == par) continue; f(f, to, now, rui[now]); } }; dfs_rui(dfs_rui, 0, -1, 0); int OFF = n; Bit bit(2 * n + 1); ll ans = 0; auto update = [&](int u) { bit.add(rui[u] + OFF, 1); }; auto query_root = [&](int u) { // DEBUG(u); // for (int i = -n; i <= n; i++) { // DEBUG(pii(i, bit.sum(i + OFF, i + 1 + OFF))); // } int p = rui[u] - a[u]; // x - p > 0 // x > p ans += bit.sum(p + 1 + OFF, 2 * n + 1); }; auto query_light = [&](int r, int u) { int p = rui[r] - a[r]; int val1 = rui[u] - p; // val1 + x - p - a[r] > 0 // x > p + a[r] - val1 ans += bit.sum(p + a[r] - val1 + 1 + OFF, 2 * n + 1); }; auto clear = [&](int u) { bit.add(rui[u] + OFF, -1); }; DSUOnTree dsu(G, 0); dsu.run_every_pair(update, query_root, query_light, clear); rep(i, n) { if (a[i] == 1) ans++; } cout << ans << endl; }