結果

問題 No.2800 Game on Tree Inverse
コンテスト
ユーザー こめだわら
提出日時 2026-02-01 21:48:02
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
結果
AC  
実行時間 833 ms / 4,000 ms
コード長 7,637 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 4,406 ms
コンパイル使用メモリ 355,716 KB
実行使用メモリ 220,324 KB
最終ジャッジ日時 2026-02-01 21:48:45
合計ジャッジ時間 35,442 ms
ジャッジサーバーID
(参考情報)
judge2 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 64
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;

#define rep(i,n) for(ll i=0;i<n;++i)
#define all(a) (a).begin(),(a).end()
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
template<class T> T div_floor(T a, T b) { return a / b - ((a ^ b) < 0 && a % b); }
template<class T> T div_ceil(T a, T b) { return a / b + ((a ^ b) > 0 && a % b); }
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>
ostream &operator<<(ostream &os, const vector<T> &a){
    if (a.empty()) return os;
    os << a.front();
    for (auto e : a | views::drop(1)){
        os << ' ' << e;
    }
    return os;
}

void dump(auto ...vs){
    ((cout << vs << ' '), ...) << endl;
}

namespace noya2 {

template<typename T, int LOG>
struct binary_trie {
    struct node {
        node *p;
        array<node*,2> ch;
        int leaf, sz;
        node () : p(nullptr), ch({nullptr,nullptr}), leaf(0), sz(0) {}
    };
    binary_trie () : lazy(0) {}
    int size(node *v){
        if (v == nullptr) return 0;
        return v->sz;
    }
    int size(){
        return size(root);
    }
    void insert(T x){
        x ^= lazy;
        node *v = root;
        for (int i = LOG-1; i >= 0; i--){
            int j = x >> i & 1;
            if (v->ch[j] == nullptr){
                v->ch[j] = new node();
                v->ch[j]->p = v;
            }
            v = v->ch[j];
        }
        v->leaf = 1;
        update(v);
        for (int i = 0; i < LOG; i++){
            v = v->p;
            update(v);
        }
    }
    void erase(T x){
        x ^= lazy;
        node *v = root;
        for (int i = LOG-1; i >= 0; i--){
            int j = x >> i & 1;
            if (v->ch[j] == nullptr) return ;
            v = v->ch[j];
        }
        v->leaf = 0;
        update(v);
        for (int i = 0; i < LOG; i++){
            node *p = v->p;
            if (size(v) == 0){
                (v == p->ch[0] ? p->ch[0] : p->ch[1]) = nullptr;
                delete v;
            }
            v = p;
            update(v);
        }
    }
    int count(T x){
        node *v = root;
        int res = 0;
        for (int i = LOG-1; i >= 0; i--){
            int j = lazy >> i & 1;
            if (x >> i & 1){
                res += size(v->ch[j]);
                v = v->ch[j^1];
            }
            else {
                v = v->ch[j];
            }
            if (v == nullptr) break;
        }
        return res;
    }
    T get(int k){
        if (k < 0 || k >= size()) return -1;
        node *v = root;
        T ans = 0;
        for (int i = LOG-1; i >= 0; i--){
            int j = lazy >> i & 1;
            if (k < size(v->ch[j])){
                v = v->ch[j];
            }
            else {
                k -= size(v->ch[j]);
                v = v->ch[j^1];
                ans |= T(1) << i;
            }
        }
        return ans;
    }
    T mex(){
        if ((T)size() == (T(1)<<LOG)) return T(1)<<LOG;
        node *v = root;
        T ans = 0;
        for (int i = LOG-1; i >= 0; i--){
            int j = lazy >> i & 1;
            if ((T)size(v->ch[j]) < (T(1)<<i)){
                v = v->ch[j];
            }
            else {
                v = v->ch[j^1];
                ans |= T(1) << i;
            }
            if (v == nullptr) break;
        }
        return ans;
    }
    T xor_all(T x){ return lazy ^= x; }
    vector<T> enumerate(){
        vector<T> ans; ans.reserve(size());
        auto dfs = [&](auto sfs, int i, T x, node *v) -> void {
            if (i == -1){
                ans.emplace_back(x^lazy);
                return ;
            }
            if (v->ch[0] != nullptr){
                sfs(sfs,i-1,x,v->ch[0]);
            }
            if (v->ch[1] != nullptr){
                sfs(sfs,i-1,x|(T(1)<<i),v->ch[1]);
            }
        };
        dfs(dfs,LOG-1,0,root);
        return ans;
    }
  private:
    T lazy;
    node *root = new node();
    void update(node *v){
        v->sz = v->leaf + size(v->ch[0]) + size(v->ch[1]);
    }
};

} // namespace noya2
using namespace noya2;

void solve() {
    ll N;
    cin>>N;
    // assert(N<5000);
    vector<vector<ll>> edge(N);
    rep(i,N-1){
        ll a,b;
        cin>>a>>b;
        a--;
        b--;
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    vector<ll> sz(N);
    vector<ll> heavy(N);
    {
        auto dfs=[&](auto self,ll cp,ll bp)->ll {
            ll v=1;
            ll hc=-1;
            ll hs=-1;
            for (ll np:edge[cp]){
                if (np==bp)continue;
                ll res=self(self,np,cp);
                v+=res;
                if (chmax(hs,res)){
                    hc=np;
                }
            }
            sz[cp]=v;
            heavy[cp]=hc;
            return v;
        };
        dfs(dfs,0,-1);
    }
    vector<ll> G(N);
    using bt = binary_trie<int,20>;
    vector<bt> bl;
    bl.reserve(N+10);
    {
        auto dfs=[&](auto self,ll cp,ll bp)->int {
            if (sz[cp]==1){
                G[cp]=1;
                bt b;
                b.insert(0);
                int idx=bl.size();
                bl.emplace_back(b);
                return idx;
            }
            ll hp=heavy[cp];
            bt &b=bl[self(self,hp,cp)];
            b.insert(G[hp]);
            ll ax=G[hp];
            for (ll np:edge[cp]){
                if (np==bp or np==hp)continue;
                self(self,np,cp);
                ax^=G[np];
            }
            b.xor_all(ax^G[hp]);
            ll now=ax;
            auto dfs2=[&](auto self,ll cp,ll bp)->void {
                ll v=0;
                v^=G[cp];
                for (ll np:edge[cp]){
                    if (np==bp)continue;
                    v^=G[np];
                }
                now^=v;
                b.insert(now);
                for (ll np:edge[cp]){
                    if (np==bp)continue;
                    self(self,np,cp);
                }
                now^=v;
                return;
            };
            for (ll np:edge[cp]){
                if (np==bp or np==hp)continue;
                dfs2(dfs2,np,cp);
            }
            G[cp]=b.mex();
            int idx=bl.size();
            bl.emplace_back(b);
            return idx;
        };
        dfs(dfs,0,-1);
    }
    // dump(G);
    vector<ll> W;
    {
        ll now=0;
        auto dfs=[&](auto self,ll cp,ll bp)->void {
            for (ll np:edge[cp]){
                if (np==bp)continue;
                now^=G[np];
            }
            if (now==0){
                W.push_back(cp);
            }
            // dump(cp,now);
            for (ll np:edge[cp]){
                if (np==bp)continue;
                now^=G[np];
                self(self,np,cp);
                now^=G[np];
            }
            for (ll np:edge[cp]){
                if (np==bp)continue;
                now^=G[np];
            }
            return;
        };
        dfs(dfs,0,-1);
    }
    cout<<"Alice"<<'\n';
    cout<<W.size()<<'\n';
    sort(all(W));
    rep(i,W.size()){
        if (i!=0)cout<<' ';
        cout<<W[i]+1;
    }
    cout<<'\n';
    return;
}


int main() {
    cin.tie(0)->sync_with_stdio(0);
    ll T=1;
    while (T--){
        solve();
    }
    return 0;
}
0