码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 3514 Codechef MARCH14 GERALD07加强版 主席树+LCT

时间:2018-08-16 00:39:46      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:str   space   chef   online   传送门   dig   temp   http   ota   

题面

题目传送门

解法

思路很妙

参见hzwer的题解

主席树+LCT……真是个毒瘤的组合

时间复杂度:\(O((m+q)\ log\ m)\)

代码

#include <bits/stdc++.h>
#define N 400010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar(); x *= f;
}
struct Node {
    int x, y;
} a[N];
struct SgementTree {
    struct Node {
        int lc, rc, cnt;
    } t[N * 35];
    int tot;
    int ins(int k, int l, int r, int x) {
        int ret = ++tot; t[ret] = t[k]; t[ret].cnt++;
        if (l == r) return ret; int mid = (l + r) >> 1;
        if (x <= mid) t[ret].lc = ins(t[k].lc, l, mid, x);
            else t[ret].rc = ins(t[ret].rc, mid + 1, r, x);
        return ret;
    }
    int query(int k1, int k2, int l, int r, int x) {
        if (l == r) return t[k2].cnt - t[k1].cnt;
        int mid = (l + r) >> 1;
        if (x <= mid) return query(t[k1].lc, t[k2].lc, l, mid, x);
        return t[t[k2].lc].cnt - t[t[k1].lc].cnt + query(t[k1].rc, t[k2].rc, mid + 1, r, x);
    }
} T;
namespace LCT {
    struct splay {
        int fa, rev, val, mn, pathfa, child[2];
    } t[N];
    int son(int x, int y) {return t[x].child[1] == y;}
    int mn(int x) {if (!x) return INT_MAX; return t[x].mn;}
    void rev(int x) {if (!x) return; t[x].rev ^= 1;}
    void update(int x) {if (!x) return; t[x].mn = min(mn(t[x].child[0]), min(mn(t[x].child[1]), t[x].val));}
    void pushdown(int x) {
        if (!x) return;
        int k = t[x].rev;
        if (k) {
            rev(x), swap(t[x].child[0], t[x].child[1]);
            rev(t[x].child[0]), rev(t[x].child[1]);
        }
    }
    void Connect(int x, int y, int k) {
        if (x) t[x].child[k] = y;
        if (y) t[y].fa = x; update(x);
    }
    void Rotate(int x) {
        int y = t[x].fa, z = t[y].fa;
        pushdown(y), pushdown(x);
        swap(t[x].pathfa, t[y].pathfa);
        int a = son(y, x), b = !a;
        Connect(z, x, son(z, y));
        Connect(y, t[x].child[b], a);
        Connect(x, y, b);
        update(y), update(x);
    }
    void Splay(int x) {
        while (t[x].fa) {
            int y = t[x].fa, z = t[y].fa;
            if (z) {
                pushdown(z), pushdown(y);
                (son(z, y) ^ son(y, x)) ? Rotate(x) : Rotate(y);
            }
            Rotate(x);
        }
    }
    void expose(int x) {
        Splay(x), pushdown(x);
        int y = t[x].child[1];
        t[y].fa = 0, t[y].pathfa = x;
        t[x].child[1] = 0, update(x);
    }
    void access(int x) {
        for (expose(x); t[x].pathfa; Splay(x)) {
            expose(t[x].pathfa);
            Connect(t[x].pathfa, x, 1);
            t[x].pathfa = 0;
        }
    }
    int findroot(int x) {
        access(x), Splay(x);
        for (pushdown(x); t[x].child[0]; x = t[x].child[0], pushdown(x));
        return x;
    }
    void evert(int x) {access(x), Splay(x), rev(x);}
    void link(int x, int y) {evert(y), t[y].pathfa = x;}
    void cut(int x, int y) {
        evert(x), access(y);
        Splay(y), pushdown(y);
        t[t[y].child[0]].fa = 0;
        t[y].child[0] = 0, update(y);
    }
    int query(int x, int y) {
        evert(x), access(y), Splay(y);
        return t[y].mn;
    }
}
int n, m, q, key, cur[N], rt[N];
int main() {
    using namespace LCT;
    read(n), read(m); read(q), read(key);
    for (int i = 1; i <= n; i++) t[i].val = t[i].mn = INT_MAX;
    int tot = n;
    for (int i = 1; i <= m; i++) {
        read(a[i].x), read(a[i].y); tot++;
        if (a[i].x == a[i].y) {cur[i] = i; continue;}
        if (findroot(a[i].x) == findroot(a[i].y)) {
            cur[i] = query(a[i].x, a[i].y); int t = cur[i] + n;
            cut(a[cur[i]].x, t), cut(t, a[cur[i]].y);
        }
        t[tot].val = t[tot].mn = i;
        link(a[i].x, tot), link(tot, a[i].y);
    }
    for (int i = 1; i <= m; i++) rt[i] = T.ins(rt[i - 1], 0, m, cur[i]);
    int ans = 0;
    while (q--) {
        int l, r; read(l), read(r);
        if (key == 1) l ^= ans, r ^= ans;
        ans = n - T.query(rt[l - 1], rt[r], 0, m, l - 1);
        cout << ans << "\n";
    }
    return 0;
}

bzoj 3514 Codechef MARCH14 GERALD07加强版 主席树+LCT

标签:str   space   chef   online   传送门   dig   temp   http   ota   

原文地址:https://www.cnblogs.com/copperoxide/p/9484276.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!