제출 #889537

#제출 시각아이디문제언어결과실행 시간메모리
889537zeta7532Railway (BOI17_railway)C++17
0 / 100
460 ms51744 KiB
#include <bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;
using ll = long long;
using Graph = vector<vector<ll>>;
using P = pair<ll,ll>;
const ll mod = 998244353;
#define fi first
#define se second
#define rep(i,n) for(ll i=0;i<n;i++)
#define all(x) x.begin(),x.end()
#define faster ios::sync_with_stdio(false);cin.tie(nullptr)
 
template<typename T>
struct RMQ1{
    const T INF=1LL<<60;
    ll N;
    vector<P> dat;
    RMQ1(ll N_):N(),dat(N_*4){
        ll x=1;
        while(N_>x) x*=2;
        N=x;
    }
    void update(ll i,T x,T y){
        i+=N-1;
        dat[i].fi=x;
        dat[i].se=y;
        while(i>0){
            i=(i-1)/2;
            if(dat[i*2+1].se<=dat[i*2+2].se){
                dat[i].fi=dat[i*2+1].fi;
                dat[i].se=dat[i*2+1].se;
            }
            if(dat[i*2+1].se>dat[i*2+2].se){
                dat[i].fi=dat[i*2+2].fi;
                dat[i].se=dat[i*2+2].se;
            }
        }
    }
    P query(ll a,ll b){return query_sub(a,b,0,0,N);}
    P query_sub(ll a,ll b,ll k,ll l,ll r){
        if(r<=a||b<=l){
            return {INF,INF};
        }else if(a<=l&&r<=b){
            return dat[k];
        }else{
            P vl=query_sub(a,b,k*2+1,l,(l+r)/2);
            P vr=query_sub(a,b,k*2+2,(l+r)/2,r);
            P q;
            if(vl.se<=vr.se){
                q.fi=vl.fi;
                q.se=vl.se;
            }
            if(vl.se>vr.se){
                q.fi=vr.fi;
                q.se=vr.se;
            }
            return q;
        }
    }
};
 
template<typename T>
struct RMQ2{
    const T INF=0;
    ll N;
    vector<T> dat;
    RMQ2(ll N_):N(),dat(N_*4){
        ll x=1;
        while(N_>x) x*=2;
        N=x;
    }
    void update(ll i,T x){
        i+=N-1;
        dat[i]+=x;
        while(i>0){
            i=(i-1)/2;
            dat[i]=dat[i*2+1]+dat[i*2+2];
        }
    }
    T query(ll a,ll b){return query_sub(a,b,0,0,N);}
    T query_sub(ll a,ll b,ll k,ll l,ll r){
        if(r<=a||b<=l){
            return INF;
        }else if(a<=l&&r<=b){
            return dat[k];
        }else{
            T vl=query_sub(a,b,k*2+1,l,(l+r)/2);
            T vr=query_sub(a,b,k*2+2,(l+r)/2,r);
            return vl+vr;
        }
    }
};
 
ll cl[100500],cr[100500];
ll Order=0;
ll dis[100500];
ll par[100500];
 
void dfs(const Graph &G,ll pos,ll dep,ll pre){
    dis[pos]=dep;
    Order++;
    cl[pos]=Order;
    for(ll to:G[pos]){
        if(to==pre) continue;
        par[to]=pos;
        dfs(G,to,dep+1,pos);
    }
    Order++;
    cr[pos]=Order;
}
 
struct centroid_decomposition{
    ll N;
    vector<vector<ll>> G;
    vector<ll> sz;
    vector<ll> par;
    vector<ll> dep;
    centroid_decomposition(const vector<vector<ll>> &G):N(G.size()),G(G),sz(N),par(N,-1),dep(N,-1) {build(0,-1,0);}
    void calcSize(ll u,ll p){
        sz[u]=1;
        for(ll v:G[u]){
            if(dep[v]==-1&&v!=p){
                calcSize(v,u);
                sz[u]+=sz[v];
            }
        }
    }
    void build(ll u,ll p,ll d){
        calcSize(u,-1);
        ll sum=sz[u];
        bool ok=false;
        ll pp=-1;
        while(!ok){
            ok=true;
            for(ll v:G[u]){
                if(dep[v]==-1&&v!=pp&&2*sz[v]>sum){
                    pp=u;
                    u=v;
                    ok=false;
                    break;
                }
            }
        }
        par[u]=p;
        dep[u]=d;
        for(ll v:G[u]){
            if(dep[v]==-1){
                build(v,u,d+1);
            }
        }
    }
    pair<vector<vector<ll>>,pair<vector<ll>,ll>> cdtree(){
        vector<vector<ll>> res(N);
        ll r;
        rep(i,N){
            if(par[i]!=-1) res[par[i]].push_back(i);
            else r=i;
        }
        return {res,{par,r}};
    }
};
 
vector<ll> bfs(vector<vector<ll>> G,ll s){
    ll N=G.size();
    vector<ll> dis(N,-1);
    dis[s]=0;
    queue<ll> que;
    que.push(s);
    while(!que.empty()){
        ll v=que.front();
        que.pop();
        for(ll nv:G[v]){
            if(dis[nv]!=-1) continue;
            dis[nv]=dis[v]+1;
            que.push(nv);
        }
    }
    return dis;
}
 
struct LCA{
    vector<vector<ll>> par;
    vector<ll> dis;
    LCA(const Graph &G,ll root=0){init (G,root);}
    void init(const Graph &G,ll root=0){
        ll v=G.size();
        ll k=1;
        while((1<<k)<v) k++;
        par.assign(k,vector<ll>(v,-1));
        dis.assign(v,-1);
        dfs(G,root,-1,0);
        for(ll i=0;i+1<k;i++){
            for(ll j=0;j<v;j++){
                if(par[i][j]<0) par[i+1][j]=-1;
                else par[i+1][j]=par[i][par[i][j]];
            }
        }
    }
    void dfs(const Graph &G,ll v,ll p,ll d){
        par[0][v]=p;
        dis[v]=d;
        for(ll nv:G[v]){
            if(nv!=p) dfs(G,nv,v,d+1);
        }
    }
    ll query(ll u,ll v){
        if(dis[u]<dis[v]) swap(u,v);
        ll K=par.size();
        for(ll k=0;k<K;k++){
            if((dis[u]-dis[v])>>k&1){
                u=par[k][u];
            }
        }
        if(u==v) return u;
        for(ll k=K-1;k>=0;k--){
            if(par[k][u]!=par[k][v]){
                u=par[k][u];
                v=par[k][v];
            }
        }
        return par[0][u];
    }
    ll query_prev(ll v,ll p){
        ll K=par.size();
        for(ll k=0;k<K;k++){
            if((dis[v]-dis[p]-1)>>k&1){
                v=par[k][v];
            }
        }
        return v;
    }
};
 
int main() {
    faster;
    ll N,Q,K;
    cin >> N >> Q >> K;
    vector<ll> A(N-1),B(N-1);
    vector<vector<ll>> G(N);
    rep(i,N-1) cin >> A[i] >> B[i];
    rep(i,N-1) A[i]--,B[i]--;
    rep(i,N-1) G[A[i]].push_back(B[i]),G[B[i]].push_back(A[i]);
    dfs(G,0,0,-1);
    vector<ll> inv(N,-1);
    rep(i,N-1){
        if(dis[A[i]]>dis[B[i]]) inv[A[i]]=i;
        if(dis[B[i]]>dis[A[i]]) inv[B[i]]=i;
    }
    RMQ2<ll> SUM(200500);
    centroid_decomposition CD(G);
    vector<vector<ll>> res=CD.cdtree().fi;
    vector<ll> PAR=CD.cdtree().se.fi;
    ll r=CD.cdtree().se.se;
    vector<ll> DIS=bfs(res,r);
    LCA ans(G);
    while(Q--){
        ll S;
        cin >> S;
        set<pair<ll,ll>> s;
        rep(i,S){
            ll t;
            cin >> t;
            t--;
            s.insert({-DIS[t],t});
        }
        while(s.size()>=2){
            auto it=*s.begin();
            s.erase(it);
            ll x=it.se;
            ll y=PAR[x];
            s.insert({-DIS[y],y});
            ll lca=ans.query(x,y);
            if(x!=lca){
                ll x_goal=ans.query_prev(x,lca);
                SUM.update(cl[x],1);
                SUM.update(cr[x_goal],-1);
            }
            if(y!=lca){
                ll y_goal=ans.query_prev(y,lca);
                SUM.update(cl[y],1);
                SUM.update(cr[y_goal],-1);
            }
        }
    }
    vector<ll> ANS;
    for(ll i=1;i<N;i++){
        ll cnt=SUM.query(1,cl[i]+1)-SUM.query(1,cl[PAR[i]]+1);
        if(cnt>=K) ANS.push_back(inv[i]+1);
    }
    sort(all(ANS));
    cout << ANS.size() << endl;
    rep(i,ANS.size()) cout << ANS[i] << " ";
    cout << endl;
    return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

railway.cpp: In function 'int main()':
railway.cpp:12:30: warning: comparison of integer expressions of different signedness: 'll' {aka 'long long int'} and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   12 | #define rep(i,n) for(ll i=0;i<n;i++)
......
  295 |     rep(i,ANS.size()) cout << ANS[i] << " ";
      |         ~~~~~~~~~~~~          
railway.cpp:295:5: note: in expansion of macro 'rep'
  295 |     rep(i,ANS.size()) cout << ANS[i] << " ";
      |     ^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...