zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    spring配合junit测试 initializationError 错误
    hashmap为什么不安全
    关于使用iframe标签自适应高度的使用
    关于highcharts(功能强大、开源、美观、图表丰富、兼容绝大多数浏览器的纯js图表库)
    富文本web编辑器(UEditor)
    css行级块级区别总结摘录
    jquery mobile 主题
    jquery mobile selectmenu下拉菜单
    jquery mobile popup 弹出窗口
    jquery mobile navbar
  • 原文地址:https://www.cnblogs.com/Lour688/p/14174941.html
Copyright © 2011-2022 走看看