new

【BZOJ3514】Codechef MARCH14 GERALD07加强版

Description

(N)个点(M)条边的无向图,询问保留图中编号在([l,r])的边的时候图中的联通块个数。

Input

第一行四个整数(N、M、K、type),代表点数、边数、询问数以及询问是否加密。
接下来(M)行,代表图中的每条边。
接下来(K)行,每行两个整数(L)(R)代表一组询问。对于(type=0)的测试点,读入的(L)(R)即为询问的(L)(R);对于(type=1)的测试点,每组询问的(L、R)应为(L) (xor) (lastans)(R) (xor) (lastans)

Output

(K)行每行一个整数代表该组询问的联通块个数。

Sample Input

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

Sample Output

2
1
3
1

HINT

对于(100%)的数据,(1≤N、M、K≤200,000)

联通块个数等于 点数-有效边数,这里的有效边也可以理解为树边,我们可以从前往后加边,用(lct)维护生成树,
设当前边(i)连接(x)(y),如果(x)(y)联通了,连上(i)并换掉路径上最早的一条边(j),并记录(a[i] = j),也就是(i)边替换掉了(j)
如果(x)(y)不联通,连上(i)后,记录(a[i] = 0),注意判自环,不连边,(a[i] = i),这样用(lct)处理出(1 <= i <= n)(a[i])
对于只有([l, r])的边的图,有效边数也就是(sum _{i = l}^{r}[a[i] < l]),多组询问,主席树维护(a[i]),在线查询

Code
#include <bits/stdc++.h>
#define rint register int
#define F(x) (t[x].fa)
#define L(x) (t[x].ch[0])
#define R(x) (t[x].ch[1])
#define get(x) (x == t[F(x)].ch[1])
#define not_root(x) (x == t[F(x)].ch[0] || x == t[F(x)].ch[1])
#define Rev(x) ({ std:: swap(L(x), R(x)), t[x].rev ^= 1; })

const int maxn = 200000 + 10;
const int inf = 1e9;
int n, m, q, typ, last_ans;
int sta[maxn * 2];
int a[maxn], ex[maxn], ey[maxn];

int read(rint x = 0, register bool f = 0, register char ch = getchar()){
	for(;!isdigit(ch);ch = getchar()) f |= ch == '-';
	for(; isdigit(ch);ch = getchar()) x = (x << 3) + (x << 1) + (ch & 15);
	return f ? -x : x ;
}

struct Node{
	bool rev;
	int val, pos;
	int fa, ch[2];
}t[maxn * 2];

int tot, root[maxn];
struct Seg{
	int siz, ls, rs;
}T[maxn * 25];

void up(rint x){
	t[x].pos = x > n ? x : 0;
	if(L(x) && t[t[L(x)].pos].val < t[t[x].pos].val) t[x].pos = t[L(x)].pos;
	if(R(x) && t[t[R(x)].pos].val < t[t[x].pos].val) t[x].pos = t[R(x)].pos;
}

void down(rint x){
	if(t[x].rev){
		if(L(x)) Rev(L(x));
		if(R(x)) Rev(R(x));
		t[x].rev = 0;
	}
}

void add(rint x, rint f, rint d){
	if(x) F(x) = f;
	if(f) t[f].ch[d] = x;
}

void rotate(rint x){
	rint y = F(x), z = F(y), gx = get(x), gy = get(y);
	if(not_root(y)) add(x, z, gy);
	else F(x) = z;
	add(t[x].ch[gx ^ 1], y, gx), add(y, x, gx ^ 1);
	up(y);
}

void splay(rint x){
	rint y = x, z = 0;
	sta[++z] = y;
	while(not_root(y)) sta[++z] = y = F(y);
	while(z) down(sta[z--]);
	while(not_root(x)){
		y = F(x);
		if(not_root(y)) get(x) != get(y) ? rotate(x) : rotate(y);
		rotate(x);
	}
	up(x);
}

void access(rint x){
	for(rint y = 0; x ;y = x, x = F(x)){
		splay(x), R(x) = y, up(x);
	}
}

void make_root(rint x){
	access(x), splay(x), Rev(x);
}

int find_root(rint x){
	access(x), splay(x);
	while(L(x)) x = L(x);
	splay(x);
	return x;
}

void link(rint x, rint y){
	make_root(x);
	if(find_root(y) != x) F(x) = y;
}

void cut(rint x, rint y){
	make_root(x);
	if(find_root(y) == x && F(y) == x && !L(y)){
		F(y) = R(x) = 0, up(x);
	}
}

#define l(x) (T[x].ls)
#define r(x) (T[x].rs)

void ins(int &rt, rint rt2, rint l, rint r, rint v){
	T[rt = ++tot] = T[rt2], T[rt].siz++;
	if(l == r) return;
	rint mid = (l + r) / 2;
	if(v <= mid) ins(l(rt), l(rt2), l, mid, v);
	else ins(r(rt), r(rt2), mid + 1, r, v);
}

int query(rint rt, rint rt2, rint l, rint r, rint v){
	if(l == r) return (l > v) ? 0 : (T[rt].siz - T[rt2].siz);
	rint mid = (l + r) / 2;
	if(v <= mid) return query(l(rt), l(rt2), l, mid, v);
	return T[l(rt)].siz - T[l(rt2)].siz + query(r(rt), r(rt2), mid + 1, r, v);
}

int main(){
#ifdef lzx
	freopen("1.in","r",stdin);
#endif
	t[0].val = inf;
	n = read(), m = read(), q = read(), typ = read();
	for(rint i = 1, x, y;i <= m; ++i){
		ex[i] = x = read(), ey[i] = y = read();
		if(x == y){ a[i] = i;continue; } // 注意自环
		if(find_root(x) != find_root(y)) a[i] = 0;
		else{
			make_root(x), access(y), splay(y);
			rint id = t[y].pos - n;
			a[i] = id;
			cut(ex[id], n + id);
			cut(n + id , ey[id]);
		}
		t[n + i].val = i, t[n + i].pos = n + i;
		link(x, n + i), link(n + i, y);
	}
	for(rint i = 1;i <= m; ++i) ins(root[i], root[i - 1], 0, m, a[i]);
	for(rint i = 1, l, r;i <= q; ++i){
		l = read() ^ (last_ans * typ), r = read() ^ (last_ans * typ);
		printf("%d
", last_ans = (n - query(root[r], root[l - 1], 0, m, l - 1)));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Lour688/p/14174941.html