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

题面

题目传送门

解法

思路很妙

参见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;
}

posted @ 2018-08-15 21:55  谜のNOIP  阅读(148)  评论(0编辑  收藏  举报