結果

問題 No.3756 Udon Network
ユーザー tsunamayo123
提出日時 2026-09-11 02:54:41
言語 C++23
(gcc 15.3.0 + boost 1.92.0 + ACL)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
WA  
実行時間 -
コード長 3,777 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 4,242 ms
コンパイル使用メモリ 393,456 KB
実行使用メモリ 64,408 KB
最終ジャッジ日時 2026-10-09 17:32:14
合計ジャッジ時間 25,669 ms
ジャッジサーバーID
(参考情報)
judge5_0 / judge4_0
このコードへのチャレンジ
(要ログイン)
サブタスク 配点 結果
Example 0 % AC * 1 WA * 7
Subtask $1$ 2 % AC * 2 WA * 13
Subtask $2$ 4 % AC * 2 WA * 20
Subtask $3$ 8 % AC * 2 WA * 7
Subtask $4$ 16 % AC * 2 WA * 8
Subtask $5$ 32 % AC * 2 WA * 8
Subtask $6$ 38 % AC * 2 WA * 51
合計 4 * 0% = 0 点
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

// 部分点6(満点)
// Kruskal Reconstruction Tree + Euler Tour + BIT(fenwick tree) + Binary lifting

#include<bits/stdc++.h>
#include<atcoder/all>
using namespace std;
using namespace atcoder;

int main(){
    int N,M,Q;
    cin>>N>>M>>Q;

    vector<int> A(N);
    for(int i=0; i<N; i++){
        cin>>A[i];
        A[i]--;
    }

    vector<pair<int,int>> B;

    vector<int> U(M),V(M),W(M);
    for(int j=0; j<M; j++){
        cin>>U[j]>>V[j]>>W[j];
        U[j]--,V[j]--;

        B.push_back({W[j],j});
    }
    sort(B.begin(),B.end());

    vector<pair<int,int>> child(2*N,{-1,-1});
    vector<int> parent(2*N,-1);
    vector<long long> weight(2*N,0);

    dsu UF(N);

    vector<int> comp(N);
    for(int i=0; i<N; i++)comp[i]=i;

    int nodes = N;

    // Kruskal Reconstruction Treeを構築してる
    for(auto [w,j]:B){
        int a=UF.leader(U[j]);
        int b=UF.leader(V[j]);

        if(a==b)continue;

        int x=comp[a];
        int y=comp[b];
        int z=nodes; nodes++;

        // 新しくwの頂点を作って、子にx,yを持たせる
        weight[z]=w;
        child[z]={x,y};

        parent[x]=parent[y]=z;

        int root=UF.merge(a,b);
        comp[root]=z;
    }
    int root=comp[UF.leader(0)];

    // DFSでEuler Tourを構築
    stack<int> st;
    st.push(root);

    vector<int> order(N);
    while(!st.empty()){
        int i=st.top();
        st.pop();

        if(i<N){
            order.push_back(i);
        }else{
            st.push(child[i].first);
            st.push(child[i].second);
        }
    }

    vector<int> L(nodes),R(nodes);
    for(int i=0; i<N; i++){
        int v=order[i];
        L[v]=R[v]=i; // 必ず葉なのでLとRは同じ
    }

    // rootに近づくほど頂点番号が大きくなってるので、小さい順に処理する
    for(int i=N; i<nodes; i++){
        auto [a,b]=child[i];
        L[i]=min(L[a],L[b]); // 頂点に入っていくとき
        R[i]=max(R[a],R[b]); // 頂点から出ていくとき
    }


    // BIT(fenwick tree)を用いて、ある頂点におけるEuler Tourの区間内の種類数を求める
    vector<int> last(N,-1);
    vector<int> cnt(nodes);

    fenwick_tree<int> fw(N);

    // R[i]が小さい順から見る -> 頂点から出ていく時間が早い順
    vector<vector<int>> r(N);
    for(int i=0; i<nodes; i++){
        r[R[i]].push_back(i);
    }

    for(int i=0; i<N; i++){
        int v=order[i];
        int c=A[v];

        // 種類数をsumで求めるために系列cの+1を移動する
        if(last[c]!=-1)fw.add(last[c],-1);
        fw.add(i,+1);

        for(int u:r[i]){
            cnt[u]=fw.sum(L[u],R[u]+1);
        }
    }

    // s_kのcnt[v]>=c_kとなる祖先vがあるとき、weight[v]が答え
    // Binary lifting(ダブリング)を使ってvを求める
    int siz=1;
    while((1<<siz)<=nodes)siz++;

    vector<vector<int>> up(siz,vector<int>(nodes,-1));

    for(int v=0; v<nodes; v++)up[0][v]=parent[v]; // vの2^0個上の祖先はvの親
    for(int j=1; j<siz; j++){
        for(int v=0; v<nodes; v++){
            if(up[j-1][v]!=-1){
                up[j][v]=up[j-1][up[j-1][v]]; // ここダブリング
            }
        }
    }

    for(int k=0; k<Q; k++){
        int s,c;
        cin>>s>>c;
        s--;

        if(cnt[s]>=c)cout<<0<<endl; // c=1のこと
        else{
            int v=s;
            for(int j=siz-1; 0<=j; j--){
                int x=up[j][v];
                // cnt[x]==cとなるギリギリまで祖先を登る(cntは単調増加)
                if(x!=-1 && cnt[x]<c){
                    v=x;
                }
            }
            int x=up[0][v]; // KRTで追加したw_jを持っている点
            cout<<weight[x]<<endl;
        }
    }
}
0