QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#534502#7513. Palindromic Beadsly_xxysML 0ms0kbC++145.5kb2024-08-27 12:51:132024-08-27 12:51:13

Judging History

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

  • [2024-08-27 12:51:13]
  • 评测
  • 测评结果:ML
  • 用时:0ms
  • 内存:0kb
  • [2024-08-27 12:51:13]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+11;

struct Node {
    int Max = 0;
    Node *l = nullptr, *r = nullptr;
};
struct Tree {
    vector <Node> info;
    vector <Node*> rt;
    int tot = 0;
    Tree(){
        info.resize(N*150), rt.resize(4*N);
    }
    Node *open(){
        return &info[tot++];
    }
    void modify(Node *&u, int pl, int pr, int pos, int v){
        if (!u) u = open();
        if (pl == pr){
            assert(!(u->Max));
        }
        u->Max = max(u->Max, v);
        if (pl == pr) return;
        int mid = (pl + pr) >> 1;
        if (mid >= pos){
            modify(u->l, pl, mid, pos, v);
        } else {
            modify(u->r, mid+1, pr, pos, v);
        }
    }
    int query(Node *u, int pl, int pr, int l, int r){
        if (!u) return 0;
        if (pl >= l && pr <= r){
            return u->Max;
        }
        int mid = (pl + pr) >> 1;
        int Max = 0;
        if (mid >= l) Max = max(Max, query(u->l, pl, mid, l, r));
        if (mid < r) Max = max(Max, query(u->r, mid+1, pr, l, r));
        return Max;
    }
};
struct order {
    int st, ed;
};

void solve(){
    int n;
    cin >> n;
    vector <vector<int>> g(n), st(n, vector<int>(19)), pairs(n);
    vector <int> dep(n), color(n);
    vector <order> ords(n); // 记录某个点子树中 dfs 序 的 最大值和最小值
    for (auto &x : color) cin >> x, x -= 1;
    for (int i = 0, a, b; i < n-1; ++ i){
        cin >> a >> b;
        -- a, -- b;
        g[a].push_back(b), g[b].push_back(a);
    }

    // 求lca部分, 二维线段树 维护 关于dfs序 的 有序数对
    int tot = 0;
    function <void(int,int)> dfs = [&](int x, int fa){
        ords[x].st =  ++ tot;
        st[x][0] = fa;
        for (int i = 1; 1<<i <= dep[x]; ++ i)
            st[x][i] = st[st[x][i-1]][i-1];
        pairs[color[x]].push_back(x);  // 记录数对, dfs 序是 从小的到大 的
        for (auto &y : g[x]){
            if (y == fa) continue;
            dep[y] = dep[x] + 1;
            dfs(y, x);
        }
        ords[x].ed = tot;
    };

    auto lca = [&](int x, int y)->int{
        if (dep[x] < dep[y]) swap(x, y);
        for (int k=0, d=dep[x]-dep[y]; 1<<k <= d; ++ k)
            if (d>>k & 1) x = st[x][k];
        if (x == y) return x;
        for (int k=(int)log2(dep[x]); k >= 0; -- k)
            if (st[x][k] != st[y][k]) x = st[x][k], y = st[y][k];
        return st[x][0];
    };

    auto Dis = [&](int x, int y)->int{
        int anc = lca(x, y);
        return dep[x] + dep[y] - 2*dep[anc];
    };

    dfs(0, 0);
    assert(tot == n);
    vector <array<int,3>> fs;
    for (int i = 0; i < n; ++ i){
        assert(pairs[i].size() < 3);
        if (pairs[i].size() == 2){
            int u = pairs[i][0], v = pairs[i][1];
            fs.push_back({u, v, Dis(u, v)});
        }
    }
    // 将 点对 降序排序
    sort(fs.begin(), fs.end(), [&](array <int,3> &a, array <int, 3> &b){
        return a[2] > b[2];
    });
    // 外层线段树
    Tree Y;
    // 更新 外层线段树的 第 x 个线段树的 第 y 个结点, 修改值为
    function<void(int,int,int,int,int,int)> modify = [&](int u, int pl, int pr, int x, int y, int v){
        Y.modify(Y.rt[u], 1, n, y, v);
        if (pl == pr) return;
        int mid = (pl + pr) >> 1;
        if (mid >= x) modify(2*u, pl, mid, x, y, v);
        else modify(2*u+1, mid+1, pr, x, y, v);
    };
    function<int(int,int,int,int,int,int,int)> ask = [&](int u, int pl, int pr, int l1, int r1, int l2, int r2){
        if (l1 > r1 || l2 > r2 || !Y.rt[u]) return 0;
        assert(Y.rt[u]);
        if (pl >= l1 && pr <= r1){
            return Y.query(Y.rt[u], 1, n, l2, r2);
        }
        int mid = (pl + pr) >> 1, Max = 0;
        if (mid >= l1) Max = max(Max, ask(2*u, pl, mid, l1, r1, l2, r2));
        if (mid < r1) Max = max(Max, ask(2*u+1, mid+1, pr, l1, r1, l2, r2));
        return Max;
    };

    vector <int> f(fs.size());
    // 查询 + dp 部分

    for (int i = 0; i < fs.size(); ++ i){
        auto &[u, v, d] = fs[i];
        int ord1, ord2, ord3, ord4;
        assert(ords[u].st < ords[v].st);
        int anc = lca(u, v);
        // 根据 u 是否是 v 的祖先, 讨论 子路径的 情况
        if (anc == u){
            int lead = -1;
            for (auto &x : g[u]){
                if (Dis(x, v) == d-1){
                    lead = x;
                    break;
                }
            }
            assert(dep[lead] > dep[u]);
            assert(lead != -1);
            ord1 = ords[lead].st-1, ord2 = ords[v].st, ord3 = ords[v].ed;
            int f1 = ask(1, 1, n, 1, ord1, ord2, ord3);
            ord1 = ords[v].st, ord2 = ords[v].ed, ord3 = ords[lead].ed+1;
            int f2 = ask(1, 1, n, ord1, ord2, ord3, n);
            f[i] = max(f1, f2)+2;
        } else {
            ord1 = ords[u].st, ord2 = ords[u].ed, ord3 = ords[v].st, ord4 = ords[v].ed;
            f[i] = ask(1, 1, n, ord1, ord2, ord3, ord4) + 2;
        }
        assert(f[i] > 0);
        modify(1, 1, n, u, v, f[i]);
    }
    int res = 1;
    for (int i = 0; i < fs.size(); ++ i){
        int d = fs[i][2];
        if (d >= 2) ++ f[i];
        res = max(res, f[i]);
    }
    assert(res <= n);
    cout << res << "\n";
}

int main(){
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int _ = 1;
    while (_--)
        solve();
    return 0;
}

/*
input:
4
1 1 2 2
1 2
2 3
2 4

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


output:

*/


Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Memory Limit Exceeded

input:

4
1 1 2 2
1 2
2 3
2 4

output:

3

result: