QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#191471#7513. Palindromic Beadsucup-team133#WA 1ms3448kbC++208.3kb2023-09-29 23:27:032023-09-29 23:27:03

Judging History

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

  • [2024-03-27 16:34:54]
  • hack成功,自动添加数据
  • (/hack/584)
  • [2024-03-27 16:18:45]
  • hack成功,自动添加数据
  • (/hack/583)
  • [2023-09-29 23:27:03]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:3448kb
  • [2023-09-29 23:27:03]
  • 提交

answer

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <random>
#include <stdio.h>
#include <fstream>
#include <functional>
#include <cassert>

using namespace std;
#define all(x) (x).begin(), (x).end()
typedef long long ll;

template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < int(v.size()); i++) os << v[i] << (i + 1 == int(v.size()) ? "" : " ");
    return os;
}

#ifdef LOCAL
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ") \n";
#else
#define debug(x) void(0)
#endif

struct HeavyLightDecomposition {
    vector<vector<int>> G;
    int n, time;
    vector<int> par, sub, dep, head, vid, vid_inv;
    HeavyLightDecomposition(int n)
        : G(n), n(n), time(0), par(n, -1), sub(n), dep(n, 0), head(n), vid(n, -1), vid_inv(n) {}
    void add_edge(int u, int v) {
        G[u].emplace_back(v);
        G[v].emplace_back(u);
    }

    void build() {
        dfs_sz(0);
        head[0] = 0;
        dfs_hld(0);
        for (int i = 0; i < n; i++) vid_inv[vid[i]] = i;
    }

    int idx(int v) { return vid[v]; }

    int la(int v, int k) {
        while (1) {
            int u = head[v];
            if (vid[v] - k >= vid[u]) return vid_inv[vid[v] - k];
            k -= vid[v] - vid[u] + 1;
            v = par[u];
        }
    }

    int distance(int u, int v) { return dep[u] + dep[v] - 2 * dep[lca(u, v)]; }

    int lca(int u, int v) {
        for (;; v = par[head[v]]) {
            if (vid[u] > vid[v]) swap(u, v);
            if (head[u] == head[v]) return u;
        }
    }

    int jump(int s, int t, int i) {
        if (i == 0) return s;
        int p = lca(s, t), d = dep[s] + dep[t] - 2 * dep[p];
        if (d < i) return -1;
        if (dep[s] - dep[p] >= i) return la(s, i);
        return la(t, d - i);
    }

    template <typename F> void query_path(int u, int v, const F& f) {
        int p = lca(u, v);
        for (auto& e : ascend(u, p)) f(e.second, e.first + 1);
        f(vid[p], vid[p] + 1);
        for (auto& e : descend(p, v)) f(e.first, e.second + 1);
    }

    vector<pair<int, int>> ascend(int u, int v) {
        vector<pair<int, int>> res;
        while (head[u] != head[v]) {
            res.emplace_back(vid[u], vid[head[u]]);
            u = par[head[u]];
        }
        if (u != v) res.emplace_back(vid[u], vid[v] + 1);
        return res;
    }

    vector<pair<int, int>> descend(int u, int v) {
        if (u == v) return {};
        if (head[u] == head[v]) return {{vid[u] + 1, vid[v]}};
        auto res = descend(u, par[head[v]]);
        res.emplace_back(vid[head[v]], vid[v]);
        return res;
    }

    void dfs_sz(int v) {
        sub[v] = 1;
        if (not G[v].empty() and G[v].front() == par[v]) swap(G[v].front(), G[v].back());
        for (int& u : G[v]) {
            if (u == par[v]) continue;
            par[u] = v;
            dep[u] = dep[v] + 1;
            dfs_sz(u);
            sub[v] += sub[u];
            if (sub[u] > sub[G[v].front()]) swap(u, G[v].front());
        }
    }

    void dfs_hld(int v) {
        vid[v] = time++;
        for (int& u : G[v]) {
            if (u == par[v]) continue;
            head[u] = (u == G[v][0] ? head[v] : u);
            dfs_hld(u);
        }
    }
};

int ceil_pow2(int n) {
    int x = 0;
    while ((1ULL << x) < n) x++;
    return x;
}

//const ll IINF = (1LL << 60) - 1;
const int IINF = 100;

struct segtree {
    using S = int;

    S op(S a, S b) { return max(a, b); }

    S e() { return -IINF; }

    int n, size, log;
    vector<S> d;

    segtree(int nn) : n(nn) {
        log = ceil_pow2(n);
        size = 1 << log;
        d = vector<S>(2 * size, e());
    }

    void set(int p, S x) {
        assert(0 <= p and p < n);
        p += size;
        d[p] = x;
        while (p > 1) {
            p >>= 1;
            d[p] = op(d[2 * p], d[2 * p + 1]);
        }
    }

    S prod(int l, int r) {
        assert(0 <= l and l <= r and r <= n);
        S sml = e(), smr = e();
        l += size, r += size;
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1, r >>= 1;
        }
        return op(sml, smr);
    }
};



int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<int> C(n);
    vector<vector<int>> c_cnt(n);
    for (int i=0;i<n;i++){
        cin >> C[i];
        C[i]--;
        c_cnt[C[i]].push_back(i);
    }
    HeavyLightDecomposition G(n);
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        G.add_edge(--u, --v);
    }

    G.build();

    
    //seg_hld: 1.頂点に乗せる値の変更 2.パス上の頂点の値のmax が処理できるデータ構造(パスが曲がる(図1のaみたいな)回分を管理)
    //seg:パスが曲がらない(図2のaみたいな)やつの回分を管理
    //ans_c: 色cを両端点とする最長回文
    //L_c,R_c: 色cの頂点で、dfs順で先、後の頂点番号
    //lca_c:L_c,R_cのlca


    //dfs(v)
    //c = 頂点 v の色
    //v = L_c の場合:chmax(ans_c,seg.query(lca_c,v)+2)

    //v = R_c の場合:chmax(ans_c,seg.query(lca_c,v)+2,seg_hld.query(L_c,lca_c))
    //v = R_c の場合:L_c = lca_c ならば seg.set(v,ans_c) そうでないなら seg_hld.set(L_c,ans_c)
    //dfs(隣接頂点)
    //v = R_c の場合:L_c = lca_c ならば seg.set(v,-INF) そうでないなら seg_hld.set(L_c,-INF)

    segtree seg_hld(n),seg_dig(n);
    vector<int> ans(n,0);
    vector<int> L(n,-1),R(n,-1);
    vector<int> dep(n,0);

    vector<int> c_lca(n,0);
    for (int c=0;c<n;c++){
        if (int(c_cnt[c].size()) > 1){
            int u = c_cnt[c][0], v = c_cnt[c][1];
            c_lca[c] = G.lca(u,v);
        }
    }

    


    auto dfs = [&](auto self,int v,int pv)->void {
        int c = C[v];

        if (int(c_cnt[c].size()) == 1){
            L[c] = v;
            R[c] = v;
            ans[c] = 1;
            seg_dig.set(dep[v],1);
            seg_hld.set(G.idx(v),1);
            for (auto nv:G.G[v]){
                if (nv == pv){continue;}
                dep[nv] = dep[v] + 1;
                self(self,nv,v);
            }
            seg_dig.set(dep[v],-1);
            seg_hld.set(G.idx(v),-1);
            return ;
        }

        if (L[c] == -1){
            //cout << "find_L" << endl;
            //cout << c << " " << v << endl;
            L[c] = v;
            ans[c] = 2 + seg_dig.prod(dep[c_lca[c]],dep[v]);

            seg_dig.set(dep[v],1);
            seg_hld.set(G.idx(v),1);
            for (auto nv:G.G[v]){
                if (nv == pv){continue;}
                dep[nv] = dep[v] + 1;
                self(self,nv,v);
            }
            seg_dig.set(dep[v],-1);
            seg_hld.set(G.idx(v),-1);
            return ;
        }

        else{
            R[c] = v;
            ans[c] = max(ans[c], 2 + seg_dig.prod(dep[c_lca[c]],dep[v]));

            int tmp = 0;
            auto sub_q = [&](int l,int r){tmp = max(tmp,seg_hld.prod(l,r));};
            G.query_path(L[c],c_lca[c],sub_q);
            ans[c] = max(ans[c], 2 + tmp);

            if (L[c] == c_lca[c]){
                seg_dig.set(dep[L[c]],ans[c]);
                seg_hld.set(G.idx(R[c]),1);
            }
            else{
                seg_hld.set(G.idx(L[c]),ans[c]);
                seg_hld.set(G.idx(R[c]),1);
            }

            for (auto nv:G.G[v]){
                if (nv == pv){continue;}
                dep[nv] = dep[v] + 1;
                self(self,nv,v);
            }

            if (L[c] == c_lca[c]){
                seg_dig.set(dep[L[c]],-1);
                seg_hld.set(G.idx(R[c]),-1);
            }
            else{
                seg_hld.set(G.idx(L[c]),-1);
                seg_hld.set(G.idx(R[c]),-1);
            }


        }



    };

    dfs(dfs,0,-1);

    cout << *max_element(ans.begin(),ans.end()) << endl;

    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3448kb

input:

4
1 1 2 2
1 2
2 3
2 4

output:

3

result:

ok single line: '3'

Test #2:

score: -100
Wrong Answer
time: 1ms
memory: 3424kb

input:

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

output:

5

result:

wrong answer 1st lines differ - expected: '4', found: '5'