結果
問題 | No.2726 Rooted Tree Nim |
ユーザー |
![]() |
提出日時 | 2024-04-14 22:05:46 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 112 ms / 2,000 ms |
コード長 | 17,381 bytes |
コンパイル時間 | 3,024 ms |
コンパイル使用メモリ | 276,804 KB |
実行使用メモリ | 29,832 KB |
最終ジャッジ日時 | 2024-10-04 01:50:51 |
合計ジャッジ時間 | 5,317 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 13 |
ソースコード
#line 2 "/Users/noya2/Desktop/Noya2_library/template/template.hpp"using namespace std;#include<bits/stdc++.h>#line 1 "/Users/noya2/Desktop/Noya2_library/template/inout_old.hpp"namespace noya2 {template <typename T, typename U>ostream &operator<<(ostream &os, const pair<T, U> &p){os << p.first << " " << p.second;return os;}template <typename T, typename U>istream &operator>>(istream &is, pair<T, U> &p){is >> p.first >> p.second;return is;}template <typename T>ostream &operator<<(ostream &os, const vector<T> &v){int s = (int)v.size();for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];return os;}template <typename T>istream &operator>>(istream &is, vector<T> &v){for (auto &x : v) is >> x;return is;}void in() {}template <typename T, class... U>void in(T &t, U &...u){cin >> t;in(u...);}void out() { cout << "\n"; }template <typename T, class... U, char sep = ' '>void out(const T &t, const U &...u){cout << t;if (sizeof...(u)) cout << sep;out(u...);}template<typename T>void out(const vector<vector<T>> &vv){int s = (int)vv.size();for (int i = 0; i < s; i++) out(vv[i]);}struct IoSetup {IoSetup(){cin.tie(nullptr);ios::sync_with_stdio(false);cout << fixed << setprecision(15);cerr << fixed << setprecision(7);}} iosetup_noya2;} // namespace noya2#line 1 "/Users/noya2/Desktop/Noya2_library/template/const.hpp"namespace noya2{const int iinf = 1'000'000'007;const long long linf = 2'000'000'000'000'000'000LL;const long long mod998 = 998244353;const long long mod107 = 1000000007;const long double pi = 3.14159265358979323;const vector<int> dx = {0,1,0,-1,1,1,-1,-1};const vector<int> dy = {1,0,-1,0,1,-1,-1,1};const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";const string alp = "abcdefghijklmnopqrstuvwxyz";const string NUM = "0123456789";void yes(){ cout << "Yes\n"; }void no(){ cout << "No\n"; }void YES(){ cout << "YES\n"; }void NO(){ cout << "NO\n"; }void yn(bool t){ t ? yes() : no(); }void YN(bool t){ t ? YES() : NO(); }} // namespace noya2#line 1 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp"namespace noya2{unsigned long long inner_binary_gcd(unsigned long long a, unsigned long long b){if (a == 0 || b == 0) return a + b;int n = __builtin_ctzll(a); a >>= n;int m = __builtin_ctzll(b); b >>= m;while (a != b) {int mm = __builtin_ctzll(a - b);bool f = a > b;unsigned long long c = f ? a : b;b = f ? b : a;a = (c - b) >> mm;}return a << min(n, m);}template<typename T> T gcd_fast(T a, T b){ return static_cast<T>(inner_binary_gcd(abs(a),abs(b))); }long long sqrt_fast(long long n) {if (n <= 0) return 0;long long x = sqrt(n);while ((x + 1) * (x + 1) <= n) x++;while (x * x > n) x--;return x;}template<typename T> T floor_div(const T n, const T d) {assert(d != 0);return n / d - static_cast<T>((n ^ d) < 0 && n % d != 0);}template<typename T> T ceil_div(const T n, const T d) {assert(d != 0);return n / d + static_cast<T>((n ^ d) >= 0 && n % d != 0);}template<typename T> void uniq(vector<T> &v){sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());}template <typename T, typename U> inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; }template <typename T, typename U> inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; }template<typename T> inline bool range(T l, T x, T r){ return l <= x && x < r; }} // namespace noya2#line 8 "/Users/noya2/Desktop/Noya2_library/template/template.hpp"#define rep(i,n) for (int i = 0; i < (int)(n); i++)#define repp(i,m,n) for (int i = (m); i < (int)(n); i++)#define reb(i,n) for (int i = (int)(n-1); i >= 0; i--)#define all(v) (v).begin(),(v).end()using ll = long long;using ld = long double;using uint = unsigned int;using ull = unsigned long long;using pii = pair<int,int>;using pll = pair<ll,ll>;using pil = pair<int,ll>;using pli = pair<ll,int>;namespace noya2{/* ~ (. _________ . /) */}using namespace noya2;#line 2 "c.cpp"#line 2 "/Users/noya2/Desktop/Noya2_library/tree/heavy_light_decomposition.hpp"#line 2 "/Users/noya2/Desktop/Noya2_library/tree/simple_tree.hpp"#line 2 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"#line 4 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"#include<ranges>#line 7 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"namespace noya2::internal {template<class E>struct csr final {csr () {}csr (int _n) : n(_n) {}csr (int _n, int m) : n(_n){start.reserve(m);elist.reserve(m);}// ACL style constructor (do not have to call build)csr (int _n, const std::vector<std::pair<int,E>> &idx_elem) : n(_n), start(_n + 2), elist(idx_elem.size()) {for (auto &[i, e] : idx_elem){start[i + 2]++;}for (int i = 1; i < n; i++){start[i + 2] += start[i + 1];}for (auto &[i, e] : idx_elem){elist[start[i + 1]++] = e;}prepared = true;}int add(int idx, E elem){int eid = start.size();start.emplace_back(idx);elist.emplace_back(elem);return eid;}void build(){if (prepared) return ;int m = start.size();std::vector<E> nelist(m);std::vector<int> nstart(n + 2, 0);for (int i = 0; i < m; i++){nstart[start[i] + 2]++;}for (int i = 1; i < n; i++){nstart[i + 2] += nstart[i + 1];}for (int i = 0; i < m; i++){nelist[nstart[start[i] + 1]++] = elist[i];}swap(elist,nelist);swap(start,nstart);prepared = true;}const auto operator[](int idx) const {return std::ranges::subrange(elist.begin()+start[idx],elist.begin()+start[idx+1]);}auto operator[](int idx){return std::ranges::subrange(elist.begin()+start[idx],elist.begin()+start[idx+1]);}const auto operator()(int idx, int l, int r) const {return std::ranges::subrange(elist.begin()+start[idx]+l,elist.begin()+start[idx]+r);}auto operator()(int idx, int l, int r){return std::ranges::subrange(elist.begin()+start[idx]+l,elist.begin()+start[idx]+r);}int n;std::vector<int> start;std::vector<E> elist;bool prepared = false;};} // namespace noya2::internal#line 5 "/Users/noya2/Desktop/Noya2_library/tree/simple_tree.hpp"namespace noya2 {struct simple_tree {internal::csr<int> g;simple_tree () {}simple_tree (int _n) : g(_n, (_n - 1)*2) {}void add_edge(int u, int v){g.add(u, v);int id = g.add(v, u);if (id + 1 == (g.n - 1)*2) g.build();}void input(int indexed = 1){for (int i = 0; i < g.n - 1; i++){int u, v; cin >> u >> v;u -= indexed, v -= indexed;add_edge(u, v);}}void input_parents(int indexed = 1){for (int i = 0; i < g.n - 1; i++){int v; cin >> v;v -= indexed;add_edge(i + 1, v);}}const auto operator[](int v) const {return g[v];}auto operator[](int v){return g[v];}};} // namespace noya2#line 4 "/Users/noya2/Desktop/Noya2_library/tree/heavy_light_decomposition.hpp"namespace noya2 {struct hld_tree {internal::csr<int> g;hld_tree () {}hld_tree (int _n, int _root = 0) : g(_n,(_n - 1)*2), n(_n), root(_root) {}hld_tree (simple_tree _g, int _root = 0) : g(_g.g), n(_g.g.n), root(_root){build();}void add_edge(int u, int v){g.add(u, v);int id = g.add(v, u);if (id + 1 == (n - 1)*2) build();}void input(int indexed = 1){for (int i = 0; i < n - 1; i++){int u, v; cin >> u >> v;u -= indexed, v -= indexed;add_edge(u, v);}}void input_parents(int indexed = 1){for (int i = 0; i < n - 1; i++){int v; cin >> v;v -= indexed;add_edge(i + 1, v);}}int depth(int v) const {return dep[v];}int parent(int v) const {if (v == root) return -1;return g[v].back();}int degree(int v) const {return g[v].size();}int subtree_size(int v) const {return sub[v];}// if d > dep[v], return -1int la(int v, int d) const {while (v != -1){int u = nxt[v];if (down[v] - d >= down[u]){v = tour[down[v] - d];break;}d -= down[v] - down[u] + 1;v = parent(u);}return v;}int lca(int u, int v) const {while (nxt[u] != nxt[v]){if (down[u] < down[v]) swap(u,v);u = parent(nxt[u]);}return dep[u] < dep[v] ? u : v;}int dist(int u, int v) const {return dep[u] + dep[v] - 2*dep[lca(u,v)];}// if d > dist(from, to), return -1int jump(int from, int to, int d) const {int l = lca(from,to);if (d <= dep[from] - dep[l]){return la(from, d);}d -= dep[from] - dep[l];if (d <= dep[to] - dep[l]){return la(to, dep[to] - dep[l] - d);}return -1;}// seg.set(index(v), X[v]);int index(int vertex) const {return down[vertex];}int index_from_edge(int u, int v) const {return (dep[u] < dep[v] ? down[v] : down[u]);}// X[vertex(i)] = seg.get(i);int vertex(int index) const {return tour[index];}int subtree_l(int v) const {return down[v];}int subtree_r(int v) const {return down[v] + sub[v];}// if r == v, return truebool is_in_subtree(int r, int v) const {return subtree_l(r) <= subtree_l(v) && subtree_l(v) < subtree_r(r);}bool is_in_path(int lv, int mv, int rv) const {return dist(lv,mv) + dist(mv,rv) == dist(lv,rv);}// dist, v1, v2tuple<int,int,int> diameter(){int v1 = max_element(dep.begin(),dep.end()) - dep.begin();vector<int> dist_from_v1(n,numeric_limits<int>::max());queue<int> que;que.push(v1);dist_from_v1[v1] = 0;while (!que.empty()){int v = que.front(); que.pop();for (int u : g[v]){if (dist_from_v1[u] > dist_from_v1[v]+1){dist_from_v1[u] = dist_from_v1[v]+1;que.push(u);}}}int v2 = max_element(dist_from_v1.begin(),dist_from_v1.end()) - dist_from_v1.begin();return make_tuple(dist_from_v1[v2],v1,v2);}// vertex array : vector<int> {from, v1, v2, ... , to}vector<int> path(int from, int to){int l = lca(from,to);const int sizf = dep[from]-dep[l], sizt = dep[to]-dep[l];vector<int> pf = {from}, pt;pf.reserve(sizf+1); pt.reserve(sizt);for (int i = 0; i < sizf; i++){from = parent(from);pf.push_back(from);}for (int i = 0; i < sizt; i++){pt.push_back(to);to = parent(to);}pf.insert(pf.end(),pt.rbegin(),pt.rend());return pf;}template<typename F>void path_query(int u, int v, bool vertex, const F &f){int l = lca(u,v);for (auto [s, t] : ascend(u, l)){f(t, s + 1);}if (vertex) f(down[l], down[l] + 1);for (auto [s, t] : descend(l, v)){f(s, t + 1);}}template<typename F>void path_noncommutative_query(int u, int v, bool vertex, const F &f){int l = lca(u,v);for (auto [s, t] : ascend(u, l)){f(s + 1, t); // l > r ok}if (vertex) f(down[l],down[l] + 1);for (auto [s, t] : descend(l, v)){f(s, t + 1); // l > r ok}}template<typename F>void subtree_query(int v, bool vertex, const F &f){f(down[v] + (vertex ? 0 : 1), down[v] + sub[v]);}// adjacent to vconst auto operator[](int v) const {return g[v];}auto operator[](int v){return g[v];}// only childconst auto operator()(int v) const {return g(v, 0, degree(v) - (v == root ? 0 : 1));}auto operator()(int v){return g(v, 0, degree(v) - (v == root ? 0 : 1));}private:int n, root;vector<int> dep, sub, down, tour, nxt;// v is ancestor of u.// enumerate [closed] intervals of down ( interval [l, r] may hold l > r ).vector<pair<int,int>> ascend(int u, int v){vector<pair<int,int>> res;while (nxt[u] != nxt[v]){res.emplace_back(down[u], down[nxt[u]]);u = parent(nxt[u]);}if (u != v) res.emplace_back(down[u], down[v]+1);return res;}// u is ancestor of v.// enumerate [closed] intervals of down ( interval [l, r] may hold l > r ).vector<pair<int,int>> descend(int u, int v){if (u == v) return {};if (nxt[u] == nxt[v]){return {pair<int,int>(down[u]+1, down[v])};}vector<pair<int,int>> res = descend(u, parent(nxt[v]));res.emplace_back(down[nxt[v]], down[v]);return res;}void build(){g.build();init_sz();init_hld();}/*setup dep, subif v is not root, g[v].back() is parent of v.if v is not leaf (i.e. v has child), g[v].front() is heavy child of v.*/void init_sz(){dep.resize(n, 0);sub.resize(n, 1);auto dfs = [&](auto sfs, int v, int f) -> void {for (int &u : g[v]){// only one chance to take parent as u.if (u == f) swap(g[v].back(), u);// twice means u is the last element of g[v], i.e. parent of v.if (u == f) break;dep[u] = dep[v]+1;sfs(sfs, u, v);sub[v] += sub[u];if (sub[g[v].front()] < sub[u]){swap(g[v].front(), u);}}};dfs(dfs, root, -1);}/*setup down, tour, nxtonly heavy child c of v, nxt[c] = nxt[v]. for other child c, nxt[c] = c.*/void init_hld(){down.resize(n);tour.resize(n);nxt.resize(n);nxt[root] = root;int clock = 0;auto dfs = [&](auto sfs, int v) -> void {down[v] = clock++;tour[down[v]] = v;// in case of no child, nothing to doif ((*this)(v).empty()) return ;// heavy childnxt[(*this)(v).front()] = nxt[v];sfs(sfs, (*this)(v).front());// other childfor (int u : (*this)(v).next()){nxt[u] = u;sfs(sfs, u);}};dfs(dfs, root);}public:struct compressed_tree : public simple_tree {using simple_tree::simple_tree;using simple_tree::operator=;hld_tree &g;compressed_tree (hld_tree &g_, vector<int> vs) : g(g_){auto comp = [&](int lv, int rv){return g.index(lv) < g.index(rv);};sort(vs.begin(),vs.end(),comp);int sz = vs.size();for (int i = 0; i < sz-1; i++){vs.emplace_back(g.lca(vs[i],vs[i+1]));}sort(vs.begin(),vs.end(),comp);vs.erase(unique(vs.begin(),vs.end()),vs.end());sz = vs.size();(*this) = simple_tree(sz);real_vertex = vs;for (int i = 0; i < sz; i++){g.virtual_vertex[real_vertex[i]] = i;}stack<int> st;st.push(0);for (int i = 1; i < sz; i++){while (!g.is_in_subtree(real_vertex[st.top()], real_vertex[i])) st.pop();(*this).add_edge(st.top(),i);st.push(i);}}vector<int> real_vertex;int real_v(int virtual_v) const {return real_vertex[virtual_v];}int virtual_v(int real_v) const {return g.virtual_vertex[real_v];}size_t size() const {return real_vertex.size();}};compressed_tree compressed_tree_gen(const vector<int> &vs){if ((int)virtual_vertex.size() != n) virtual_vertex.resize(n);return compressed_tree(*this, vs);}vector<int> virtual_vertex;};} // namespace noya2#line 4 "c.cpp"void solve(){int n; in(n);ll k; in(k);hld_tree g(n);g.input();vector<ll> a(n); in(a);ll x = 0;rep(i,n){if (g.depth(i) % 2 == 0) continue;x ^= (a[i] % (k+1));}out(x == 0 ? "P" : "K");}int main(){int t = 1; in(t);while (t--) { solve(); }}