QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#835825#9924. Reconstructionucup-team5243#WA 364ms65736kbC++1714.4kb2024-12-28 14:51:172024-12-28 14:51:18

Judging History

你现在查看的是最新测评结果

  • [2024-12-31 17:12:54]
  • hack成功,自动添加数据
  • (/hack/1320)
  • [2024-12-28 14:51:18]
  • 评测
  • 测评结果:WA
  • 用时:364ms
  • 内存:65736kb
  • [2024-12-28 14:51:17]
  • 提交

answer

#ifdef NACHIA
#define _GLIBCXX_DEBUG
#else
#define NDEBUG
#endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using i64 = long long;
using u64 = unsigned long long;
#define rep(i,n) for(int i=0; i<int(n); i++)
const i64 INF = 1001001001001001001;
template<typename A> void chmin(A& l, const A& r){ if(r < l) l = r; }
template<typename A> void chmax(A& l, const A& r){ if(l < r) l = r; }
using namespace std;

#include <utility>

namespace nachia{

template<class Elem>
class CsrArray{
public:
    struct ListRange{
        using iterator = typename std::vector<Elem>::iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        Elem& operator[](int i) const { return begi[i]; }
    };
    struct ConstListRange{
        using iterator = typename std::vector<Elem>::const_iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        const Elem& operator[](int i) const { return begi[i]; }
    };
private:
    int m_n;
    std::vector<Elem> m_list;
    std::vector<int> m_pos;
public:
    CsrArray() : m_n(0), m_list(), m_pos() {}
    static CsrArray Construct(int n, std::vector<std::pair<int, Elem>> items){
        CsrArray res;
        res.m_n = n;
        std::vector<int> buf(n+1, 0);
        for(auto& [u,v] : items){ ++buf[u]; }
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        res.m_list.resize(buf[n]);
        for(int i=(int)items.size()-1; i>=0; i--){
            res.m_list[--buf[items[i].first]] = std::move(items[i].second);
        }
        res.m_pos = std::move(buf);
        return res;
    }
    static CsrArray FromRaw(std::vector<Elem> list, std::vector<int> pos){
        CsrArray res;
        res.m_n = pos.size() - 1;
        res.m_list = std::move(list);
        res.m_pos = std::move(pos);
        return res;
    }
    ListRange operator[](int u) { return ListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    ConstListRange operator[](int u) const { return ConstListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    int size() const { return m_n; }
    int fullSize() const { return (int)m_list.size(); }
};

} // namespace nachia
#include <cassert>

namespace nachia{


struct Graph {
public:
    struct Edge{
        int from, to;
        void reverse(){ std::swap(from, to); }
        int xorval() const { return from ^ to; }
    };
    Graph() : m_n(0), m_e(0), m_isUndir(false) {}
    explicit Graph(int n, bool undirected = false, int m = 0) : m_n(n), m_e(m), m_isUndir(undirected) {}
    explicit Graph(int n, const std::vector<std::pair<int, int>>& edges, int undirected = false) : m_n(n), m_isUndir(undirected){
        m_e.resize(edges.size());
        for(std::size_t i=0; i<edges.size(); i++) m_e[i] = { edges[i].first, edges[i].second };
    }
    template<class Cin>
    static Graph Input(Cin& cin, int n, bool undirected, int m, int offset = 0){
        Graph res(n, undirected, m);
        for(int i=0; i<m; i++){
            int u, v; cin >> u >> v;
            res[i].from = u - offset;
            res[i].to = v - offset;
        }
        return res;
    }
    int numVertices() const noexcept { return m_n; }
    int numEdges() const noexcept { return int(m_e.size()); }
    int addNode() noexcept { return m_n++; }
    int addEdge(int from, int to){ m_e.push_back({ from, to }); return numEdges() - 1; }
    Edge& operator[](int ei) noexcept { return m_e[ei]; }
    const Edge& operator[](int ei) const noexcept { return m_e[ei]; }
    Edge& at(int ei) { return m_e.at(ei); }
    const Edge& at(int ei) const { return m_e.at(ei); }
    auto begin(){ return m_e.begin(); }
    auto end(){ return m_e.end(); }
    auto begin() const { return m_e.begin(); }
    auto end() const { return m_e.end(); }
    bool isUndirected() const noexcept { return m_isUndir; }
    void reverseEdges() noexcept { for(auto& e : m_e) e.reverse(); }
    void contract(int newV, const std::vector<int>& mapping){
        assert(numVertices() == int(mapping.size()));
        for(int i=0; i<numVertices(); i++) assert(0 <= mapping[i] && mapping[i] < newV);
        for(auto& e : m_e){ e.from = mapping[e.from]; e.to = mapping[e.to]; }
        m_n = newV;
    }
    std::vector<Graph> induce(int num, const std::vector<int>& mapping) const {
        int n = numVertices();
        assert(n == int(mapping.size()));
        for(int i=0; i<n; i++) assert(-1 <= mapping[i] && mapping[i] < num);
        std::vector<int> indexV(n), newV(num);
        for(int i=0; i<n; i++) if(mapping[i] >= 0) indexV[i] = newV[mapping[i]]++;
        std::vector<Graph> res; res.reserve(num);
        for(int i=0; i<num; i++) res.emplace_back(newV[i], isUndirected());
        for(auto e : m_e) if(mapping[e.from] == mapping[e.to] && mapping[e.to] >= 0) res[mapping[e.to]].addEdge(indexV[e.from], indexV[e.to]);
        return res;
    }
    CsrArray<int> getEdgeIndexArray(bool undirected) const {
        std::vector<std::pair<int, int>> src;
        src.reserve(numEdges() * (undirected ? 2 : 1));
        for(int i=0; i<numEdges(); i++){
            auto e = operator[](i);
            src.emplace_back(e.from, i);
            if(undirected) src.emplace_back(e.to, i);
        }
        return CsrArray<int>::Construct(numVertices(), src);
    }
    CsrArray<int> getEdgeIndexArray() const { return getEdgeIndexArray(isUndirected()); }
    CsrArray<int> getAdjacencyArray(bool undirected) const {
        std::vector<std::pair<int, int>> src;
        src.reserve(numEdges() * (undirected ? 2 : 1));
        for(auto e : m_e){
            src.emplace_back(e.from, e.to);
            if(undirected) src.emplace_back(e.to, e.from);
        }
        return CsrArray<int>::Construct(numVertices(), src);
    }
    CsrArray<int> getAdjacencyArray() const { return getAdjacencyArray(isUndirected()); }
private:
    int m_n;
    std::vector<Edge> m_e;
    bool m_isUndir;
};

} // namespace nachia

namespace nachia{

struct HeavyLightDecomposition{
private:

    int N;
    std::vector<int> P;
    std::vector<int> PP;
    std::vector<int> PD;
    std::vector<int> D;
    std::vector<int> I;

    std::vector<int> rangeL;
    std::vector<int> rangeR;

public:

    HeavyLightDecomposition(const CsrArray<int>& E = CsrArray<int>::Construct(1, {}), int root = 0){
        N = E.size();
        P.assign(N, -1);
        I.assign(N, 0); I[0] = root;
        int iI = 1;
        for(int i=0; i<iI; i++){
            int p = I[i];
            for(int e : E[p]) if(P[p] != e){
                I[iI++] = e;
                P[e] = p;
            }
        }
        std::vector<int> Z(N, 1);
        std::vector<int> nx(N, -1);
        PP.resize(N);
        for(int i=0; i<N; i++) PP[i] = i;
        for(int i=N-1; i>=1; i--){
            int p = I[i];
            Z[P[p]] += Z[p];
            if(nx[P[p]] == -1) nx[P[p]] = p;
            if(Z[nx[P[p]]] < Z[p]) nx[P[p]] = p;
        }

        for(int p : I) if(nx[p] != -1) PP[nx[p]] = p;

        PD.assign(N,N);
        PD[root] = 0;
        D.assign(N,0);
        for(int p : I) if(p != root){
            PP[p] = PP[PP[p]];
            PD[p] = std::min(PD[PP[p]], PD[P[p]]+1);
            D[p] = D[P[p]]+1;
        }
        
        rangeL.assign(N,0);
        rangeR.assign(N,0);
        
        for(int p : I){
            rangeR[p] = rangeL[p] + Z[p];
            int ir = rangeR[p];
            for(int e : E[p]) if(P[p] != e) if(e != nx[p]){
                rangeL[e] = (ir -= Z[e]);
            }
            if(nx[p] != -1){
                rangeL[nx[p]] = rangeL[p] + 1;
            }
        }

        for(int i=0; i<N; i++) I[rangeL[i]] = i;
    }
    
    HeavyLightDecomposition(const Graph& tree, int root = 0)
        : HeavyLightDecomposition(tree.getAdjacencyArray(true), root) {}

    int numVertices() const { return N; }
    int depth(int p) const { return D[p]; }
    int toSeq(int vtx) const { return rangeL[vtx]; }
    int toVtx(int seqidx) const { return I[seqidx]; }
    int toSeq2In(int vtx) const { return rangeL[vtx] * 2 - D[vtx]; }
    int toSeq2Out(int vtx) const { return rangeR[vtx] * 2 - D[vtx] - 1; }
    int parentOf(int v) const { return P[v]; }
    int heavyRootOf(int v) const { return PP[v]; }
    int heavyChildOf(int v) const {
        if(toSeq(v) == N-1) return -1;
        int cand = toVtx(toSeq(v) + 1);
        if(PP[v] == PP[cand]) return cand;
        return -1;
    }

    int lca(int u, int v) const {
        if(PD[u] < PD[v]) std::swap(u, v);
        while(PD[u] > PD[v]) u = P[PP[u]];
        while(PP[u] != PP[v]){ u = P[PP[u]]; v = P[PP[v]]; }
        return (D[u] > D[v]) ? v : u;
        /*
        if(rangeL[u] > rangeL[v]) std::swap(u, v);
        int h = rangeL[u];
        while(h < rangeL[PP[v]]){ v = P[PP[v]]; }
        return rangeL[v] <= h ? v : u;
        */
    }

    int dist(int u, int v) const {
        return depth(u) + depth(v) - depth(lca(u,v)) * 2;
    }

    struct Range{
        int l; int r;
        int size() const { return r-l; }
        bool includes(int x) const { return l <= x && x < r; }
    };

    std::vector<Range> path(int r, int c, bool include_root = true, bool reverse_path = false) const {
        if(PD[c] < PD[r]) return {};
        std::vector<Range> res(PD[c]-PD[r]+1);
        for(int i=0; i<(int)res.size()-1; i++){
            res[i] = { rangeL[PP[c]], rangeL[c]+1 };
            c = P[PP[c]];
        }
        if(PP[r] != PP[c] || D[r] > D[c]) return {};
        res.back() = { rangeL[r]+(include_root?0:1), rangeL[c]+1 };
        if(res.back().l == res.back().r) res.pop_back();
        if(!reverse_path) std::reverse(res.begin(),res.end());
        else for(auto& a : res) a = { N - a.r, N - a.l };
        return res;
    }

    Range subtree(int p) const { return { rangeL[p], rangeR[p] }; }

    int median(int x, int y, int z) const {
        return lca(x,y) ^ lca(y,z) ^ lca(x,z);
    }

    int la(int from, int to, int d) const {
        if(d < 0) return -1;
        int g = lca(from,to);
        int dist0 = D[from] - D[g] * 2 + D[to];
        if(dist0 < d) return -1;
        int p = from;
        if(D[from] - D[g] < d){ p = to; d = dist0 - d; }
        while(D[p] - D[PP[p]] < d){
            d -= D[p] - D[PP[p]] + 1;
            p = P[PP[p]];
        }
        return I[rangeL[p] - d];
    }

    struct ChildrenIterRange {
    struct Iter {
        const HeavyLightDecomposition& hld; int s;
        int operator*() const { return hld.toVtx(s); }
        Iter& operator++(){
            s += hld.subtree(hld.I[s]).size();
            return *this;
        }
        Iter operator++(int) const { auto a = *this; return ++a; }
        bool operator==(Iter& r) const { return s == r.s; }
        bool operator!=(Iter& r) const { return s != r.s; }
    };
        const HeavyLightDecomposition& hld; int v;
        Iter begin() const { return { hld, hld.rangeL[v] + 1 }; }
        Iter end() const { return { hld, hld.rangeR[v] }; }
    };
    ChildrenIterRange children(int v) const {
        return ChildrenIterRange{ *this, v };
    }
};

} // namespace nachia

void testcase(){
    int N; cin >> N;
    vector<vector<int>> T(N);
    rep(i,N-1){
        int u,v; cin >> u >> v; u--; v--;
        T[u].push_back(v);
        T[v].push_back(u);
    }
    auto X = nachia::Graph::Input(cin, N, true, N-1, 1);
    auto adjX = X.getAdjacencyArray();
    auto hld = nachia::HeavyLightDecomposition(X, 0);
    vector<int> imos(N+1);
    auto addSubtree = [&](int u, int v){
        //cout << "  subtree " << u << " -> " << v << endl;
        auto [l,r] = hld.subtree(v);
        if(l <= hld.toSeq(u) && hld.toSeq(u) < r){
            imos[0] += 1;
            imos[l] -= 1;
            imos[r] += 1;
            imos[N] -= 1;
        } else {
            imos[l+1] += 1;
            imos[r] -= 1;
        }
    };
    auto addVtx = [&](int v){
        //cout << "  vtx " << v << endl;
        int p = hld.toSeq(v);
        imos[p] += 1;
        imos[p+1] -= 1;
    };
    //cout << "##" << endl;
    auto bad = [&](){ cout << string(N, '0') << "\n"; };
    rep(v,N){
        //cout << "v = " << v << endl;
        if(T[v].size() + 1 < adjX[v].size()){ bad(); return; }
        vector<int> F(T[v].size());
        rep(i,T[v].size()) F[i] = hld.la(v, T[v][i], 1);
        vector<int> G = F;
        sort(G.begin(), G.end());
        vector<int> cnt;
        for(int w : adjX[v]) cnt.push_back(
            upper_bound(G.begin(), G.end(), w) - lower_bound(G.begin(), G.end(), w));
        int cntcnt1 = 0;
        for(auto a : cnt) if(a == 1) cntcnt1++;
        if(T[v].size() + 1 == adjX[v].size()){
            if(cntcnt1 != int(T[v].size())){ bad(); return; }
            rep(i,adjX[v].size()) if(cnt[i] != 1){
                addSubtree(v, adjX[v][i]);
                addVtx(adjX[v][i]);
            }
        } else if(T[v].size() == adjX[v].size()){
            addVtx(v);
            if(cntcnt1 != int(T[v].size())){ bad(); return; }
            for(int w : T[v]){ addSubtree(v, w); addVtx(w); }
        } else {
            if(cntcnt1 != int(adjX[v].size()-1)){ bad(); return; }
            int maxdist = v;
            int way = -1;
            rep(i,adjX[v].size()) if(cnt[i] != 1) way = adjX[v][i];
            rep(i,G.size())
            rep(i,T[v].size()){
                int w = T[v][i];
                if(way == F[i]){
                    int med = hld.median(v, maxdist, w);
                    if(med == w) continue;
                    if(med != maxdist){ bad(); return; }
                    maxdist = w;
                }
            }
            addSubtree(v, maxdist);
            addVtx(maxdist);
        }
    }
    rep(i,N) imos[i+1] += imos[i];
    //rep(i,N){ cout << imos[hld.toSeq(i)] << " "; } cout << endl;
    rep(v,N){
        int p = hld.toSeq(v);
        if(imos[p] == N){
            cout << "1";
        } else{
            cout << "0";
        }
    } cout << "\n";
}

int main(){
    ios::sync_with_stdio(false); cin.tie(nullptr);
    //int T; cin >> T;
    //rep(t,T) testcase();
    testcase();
    return 0;
}

详细

Test #1:

score: 100
Accepted
time: 0ms
memory: 3496kb

input:

3
1 2
2 3
2 1
1 3

output:

001

result:

ok single line: '001'

Test #2:

score: 0
Accepted
time: 0ms
memory: 3560kb

input:

6
1 3
3 4
3 6
4 5
5 2
1 3
1 4
4 5
5 2
3 6

output:

010110

result:

ok single line: '010110'

Test #3:

score: 0
Accepted
time: 0ms
memory: 3840kb

input:

1

output:

1

result:

ok single line: '1'

Test #4:

score: 0
Accepted
time: 0ms
memory: 3548kb

input:

2
1 2
1 2

output:

11

result:

ok single line: '11'

Test #5:

score: -100
Wrong Answer
time: 364ms
memory: 65736kb

input:

500000
321614 78209
64619 204431
81539 336200
128603 201377
132521 391792
41587 137224
174146 381680
341915 451206
493371 256005
259794 168656
161914 462290
105839 333679
377214 267008
283062 457340
219692 196741
123276 321510
473789 410796
498171 203543
178249 456921
255509 449152
294196 457566
277...

output:

000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...

result:

wrong answer 1st lines differ - expected: '000000000000000000000000000000...0000000000000000000000000000000', found: '000000000000000000000000000000...0000000000000000000000000000000'