HDU - 5398 GCD Tree LCT

HDU - 5398

Pretreatment maintain the maximum spanning every moment of it LCT maintenance on it.

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 3e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int n;
LL ans[N];
LL now;
int tot;
int U[N], V[N];
vector<int> fac[N];

struct LCT {
#define l(x) (ch[x][0])
#define r(x) (ch[x][1])
    int fa[N], ch[N][2], rev[N], sz[N], q[N];
    PII w[N], mn[N];
    void init(int n) {
        for(int i = 0; i <= n; i++) {
            fa[i] = rev[i] = 0;
            sz[i] = 1;
            mn[i] = w[i] = mk(1000000, i);
            ch[i][0] = ch[i][1] = 0;
        }
        tot = n + 1;
    }
    inline bool isroot(int x) {
        return l(fa[x]) != x && r(fa[x]) != x;
    }
    inline void pull(int x) {
        sz[x] = sz[l(x)] + sz[r(x)] + 1;
        mn[x] = w[x];
        chkmin(mn[x], mn[l(x)]);
        chkmin(mn[x], mn[r(x)]);
    }
    inline void push(int x) {
        if(rev[x]) {
            rev[x] = 0; swap(l(x), r(x));
            rev[l(x)] ^= 1; rev[r(x)] ^= 1;
        }
    }
    inline void rot(int x) {
        int y = fa[x], z = fa[y], l, r;
        if(ch[y][0] == x) l = 0, r = l ^ 1;
        else l = 1, r = l ^ 1;
        if(!isroot(y)) {
            if(l(z) == y) l(z) = x;
            else r(z) = x;
        }
        fa[x] = z; fa[y] = x; fa[ch[x][r]]=y;
        ch[y][l] = ch[x][r]; ch[x][r] = y;
        pull(y); pull(x);
    }
    inline void splay(int x) {
        int top = 1; q[top] = x;
        for(int i = x; !isroot(i); i = fa[i]) q[++top] = fa[i];
        for(int i = top; i; i--) push(q[i]);
        while(!isroot(x)) {
            int y = fa[x], z = fa[y];
            if(!isroot(y)) {
                if((l(y) == x) ^ (l(z) == y)) rot(x);
                else rot(y);
            }
            rot(x);
        }
    }
    inline void access(int x) {
        for(int y = 0; x; y = x, x = fa[x]) {
            splay(x);
            r(x) = y;
            pull(x);
        }
    }
    inline void makeroot(int x) {
        access(x); splay(x); rev[x] ^= 1;
    }
    inline int findroot(int x) {
        access(x); splay(x);
        while(l(x)) x = l(x);
        return x;
    }
    inline void split(int x, int y) {
        makeroot(x); access(y); splay(y);
    }
    inline void link(int x, int y) {
        makeroot(x); fa[x] = y; splay(x);
    }
    inline void cut(int x, int y) {
        split(x, y);
        if(l(y) == x) l(y) = 0, fa[x] = 0;
    }
    void change(int x, int y, int weight) {
        if(findroot(x) != findroot(y)) {
            ++tot;
            w[tot] = mk(weight, tot);
            U[tot] = x; V[tot] = y;
            sz[tot] = 1;
            link(x, tot);
            link(y, tot);
            now += weight;
            return;
        }

        makeroot(x);
        access(y);
        splay(y);
        PII minVal = mn[y];

        if(minVal.fi >= weight) return;
        cut(minVal.se, V[minVal.se]);
        cut(minVal.se, U[minVal.se]);
        now -= minVal.fi;

        w[minVal.se] = mk(weight, minVal.se);
        U[minVal.se] = x; V[minVal.se] = y;
        sz[minVal.se] = 1;
        link(x, minVal.se);
        link(y, minVal.se);
        now += weight;
    }
} lct;

int main() {
    for(int i = 1; i <= 100000; i++) {
        for(int j = i + i; j <= 100000; j += i) {
            fac[j].push_back(i);
        }
    }

    lct.init(100000);

    for(int i = 2; i <= 100000; i++) {
        for(int j : fac[i]) {
            lct.change(i, j, j);
        }
        ans[i] = now;
    }

    while(scanf("%d", &n) != EOF) {
        printf("%lld\n", ans[n]);
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/CJLHY/p/11274169.html