Submission #1359211

#TimeUsernameProblemLanguageResultExecution timeMemory
1359211retardeTourism (JOI23_tourism)C++20
Compilation error
0 ms0 KiB
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")

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

using ll = long long;

const int MAXN = 100000 + 5;
const int LOGE = 20;

struct FastScanner {
    static const int S = 1 << 20;
    int idx, size;
    char buf[S];

    FastScanner() : idx(0), size(0) {}

    inline char getChar() {
        if (idx >= size) {
            size = fread(buf, 1, S, stdin);
            idx = 0;
            if (size == 0) return 0;
        }
        return buf[idx++];
    }

    template<class T>
    inline bool readInt(T &out) {
        char c;
        T sign = 1;
        T num = 0;

        c = getChar();
        if (!c) return false;

        while (c != '-' && (c < '0' || c > '9')) {
            c = getChar();
            if (!c) return false;
        }

        if (c == '-') {
            sign = -1;
            c = getChar();
        }

        while (c >= '0' && c <= '9') {
            num = num * 10 + (c - '0');
            c = getChar();
        }

        out = num * sign;
        return true;
    }
};

int n, m, q;
vector<int> adj[MAXN];

int c[MAXN];
int tin[MAXN], firstOcc[MAXN], depthArr[MAXN], tinToNode[MAXN], cntNode[MAXN];
int timerDfs;
vector<int> euler;
int lg2_[2 * MAXN];
int st[LOGE][2 * MAXN];

inline int betterDepth(int a, int b) {
    return depthArr[a] < depthArr[b] ? a : b;
}

void buildDfsIterative() {
    vector<int> parent(n + 1, 0), it(n + 1, 0), stk;
    stk.reserve(n);

    timerDfs = 0;
    euler.clear();
    euler.reserve(2 * n);

    stk.push_back(1);
    parent[1] = 0;
    depthArr[1] = 0;
    tin[1] = timerDfs;
    tinToNode[timerDfs] = 1;
    timerDfs++;
    firstOcc[1] = 0;
    euler.push_back(1);

    while (!stk.empty()) {
        int u = stk.back();

        if (it[u] == (int)adj[u].size()) {
            stk.pop_back();
            if (!stk.empty()) euler.push_back(stk.back());
            continue;
        }

        int v = adj[u][it[u]++];
        if (v == parent[u]) continue;

        parent[v] = u;
        depthArr[v] = depthArr[u] + 1;
        tin[v] = timerDfs;
        tinToNode[timerDfs] = v;
        timerDfs++;
        firstOcc[v] = (int)euler.size();
        euler.push_back(v);
        stk.push_back(v);
    }
}

void buildLca() {
    int sz = (int)euler.size();

    lg2_[1] = 0;
    for (int i = 2; i <= sz; i++) lg2_[i] = lg2_[i >> 1] + 1;

    for (int i = 0; i < sz; i++) st[0][i] = euler[i];

    for (int k = 1; k < LOGE; k++) {
        int len = 1 << k;
        int half = len >> 1;
        for (int i = 0; i + len <= sz; i++) {
            st[k][i] = betterDepth(st[k - 1][i], st[k - 1][i + half]);
        }
    }
}

inline int lca(int u, int v) {
    int l = firstOcc[u];
    int r = firstOcc[v];
    if (l > r) swap(l, r);
    int k = lg2_[r - l + 1];
    return betterDepth(st[k][l], st[k][r - (1 << k) + 1]);
}

inline int distTree(int u, int v) {
    int w = lca(u, v);
    return depthArr[u] + depthArr[v] - 2 * depthArr[w];
}

ll hilbertOrder(int x, int y, int pow = 17, int rot = 0) {
    if (pow == 0) return 0;
    int hpow = 1 << (pow - 1);
    int seg;

    if (x < hpow) {
        seg = (y < hpow ? 0 : 3);
    } else {
        seg = (y < hpow ? 1 : 2);
    }

    seg = (seg + rot) & 3;
    static const int rotateDelta[4] = {3, 0, 0, 1};

    int nx = x & (hpow - 1);
    int ny = y & (hpow - 1);
    int nrot = (rot + rotateDelta[seg]) & 3;

    ll subSquareSize = 1LL << (2 * pow - 2);
    ll ord = seg * subSquareSize;
    ll add = hilbertOrder(nx, ny, pow - 1, nrot);

    if (seg == 1 || seg == 2) ord += add;
    else ord += subSquareSize - add - 1;

    return ord;
}

struct Query {
    int l, r, id;
    ll ord;
};

set<int> activeTin;
ll curans = 0;

inline int nodeFromTin(int t) {
    return tinToNode[t];
}

inline void activateNode(int v) {
    int t = tin[v];

    if (activeTin.empty()) {
        activeTin.insert(t);
        return;
    }

    auto it = activeTin.lower_bound(t);

    int nxtTin = (it == activeTin.end() ? *activeTin.begin() : *it);

    int prvTin;
    if (it == activeTin.begin()) prvTin = *activeTin.rbegin();
    else {
        auto jt = it;
        --jt;
        prvTin = *jt;
    }

    int prv = nodeFromTin(prvTin);
    int nxt = nodeFromTin(nxtTin);

    curans += distTree(prv, v) + distTree(v, nxt) - distTree(prv, nxt);
    activeTin.insert(t);
}

inline void deactivateNode(int v) {
    int t = tin[v];

    if ((int)activeTin.size() == 1) {
        activeTin.erase(t);
        return;
    }

    auto it = activeTin.find(t);

    auto itPrev = it;
    if (itPrev == activeTin.begin()) itPrev = prev(activeTin.end());
    else --itPrev;

    auto itNext = next(it);
    if (itNext == activeTin.end()) itNext = activeTin.begin();

    int prv = nodeFromTin(*itPrev);
    int nxt = nodeFromTin(*itNext);

    curans -= distTree(prv, v) + distTree(v, nxt) - distTree(prv, nxt);
    activeTin.erase(it);
}

inline void addPos(int idx) {
    int v = c[idx];
    cntNode[v]++;
    if (cntNode[v] == 1) activateNode(v);
}

inline void removePos(int idx) {
    int v = c[idx];
    cntNode[v]--;
    if (cntNode[v] == 0) deactivateNode(v);
}

int main() {
    FastScanner fs;

    fs.readInt(n);
    fs.readInt(m);
    fs.readInt(q);

    for (int i = 1; i < n; i++) {
        int u, v;
        fs.readInt(u);
        fs.readInt(v);
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    buildDfsIterative();
    buildLca();

    for (int i = 0; i < m; i++) fs.readInt(c[i]);

    vector<Query> queries(q);
    for (int i = 0; i < q; i++) {
        int l, r;
        fs.readInt(l);
        fs.readInt(r);
        --l;
        --r;
        queries[i] = {l, r, i, hilbertOrder(l, r)};
    }

    sort(queries.begin(), queries.end(), [](const Query &a, const Query &b) {
        return a.ord < b.ord;
    });

    vector<ll> ans(q);

    int L = 0;
    int R = -1;

    for (const Query &qq : queries) {
        while (L > qq.l) addPos(--L);
        while (R < qq.r) addPos(++R);
        while (L < qq.l) removePos(L++);
        while (R > qq.r) removePos(R--);

        ans[qq.id] = curans / 2 + 1;
    }

    string out;
    out.reserve(q * 4);

    for (int i = 0; i < q; i++) {
        out += to_string(ans[i]);
        out += '\n';
    }

    fwrite(out.c_str(), 1, out.size(), stdout);

    return 0;
}

Compilation message (stderr)

In file included from /usr/include/c++/13/string:43,
                 from /usr/include/c++/13/bitset:52,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:52,
                 from tourism.cpp:4:
/usr/include/c++/13/bits/allocator.h: In destructor 'constexpr std::__cxx11::basic_string<char>::_Alloc_hider::~_Alloc_hider()':
/usr/include/c++/13/bits/allocator.h:184:7: error: inlining failed in call to 'always_inline' 'constexpr std::allocator< <template-parameter-1-1> >::~allocator() noexcept [with _Tp = char]': target specific option mismatch
  184 |       ~allocator() _GLIBCXX_NOTHROW { }
      |       ^
In file included from /usr/include/c++/13/string:54:
/usr/include/c++/13/bits/basic_string.h:181:14: note: called from here
  181 |       struct _Alloc_hider : allocator_type // TODO check __is_final
      |              ^~~~~~~~~~~~