zoukankan      html  css  js  c++  java
  • 【LOJ121】「离线可过」动态图连通性

    【LOJ121】「离线可过」动态图连通性

    题面

    LOJ

    题解

    线段树分治的经典应用

    可以发现每个边出现的时间是一个区间

    而我们每个询问是一个点

    所以我们将所有边的区间打到一颗线段树上面去

    询问每个叶子用并查集维护节点的联通性就好了

    注意并查集因为要撤消所以只能用按秩合并保证复杂度

    具体实现详见代码

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm>
    #include <vector> 
    using namespace std; 
    inline int gi() { 
        register int data = 0, w = 1; 
        register char ch = 0; 
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar(); 
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
        return w * data; 
    }
    const int MAX_N = 5e3 + 5;
    const int MAX_M = 5e5 + 5; 
    int N, M, tim[MAX_N][MAX_N]; 
    vector<int> vec[MAX_M << 2]; 
    struct Query { int x, y, t, id; } q[MAX_M], lq[MAX_M], rq[MAX_M]; 
    struct Modify { int x, y; } p[MAX_M]; 
    bool ans[MAX_M]; 
    int fa[MAX_N], rnk[MAX_N];
    pair<int, int> stk[MAX_N]; int top; 
    int getf(int x) { return x == fa[x] ? x : getf(fa[x]); } 
    void unite(int x, int y) { 
    	x = getf(x), y = getf(y);
    	if (x == y) return ; 
    	if (rnk[x] < rnk[y]) swap(x, y); 
    	fa[y] = x; 
    	stk[++top] = make_pair(y, rnk[y]);
    	if (rnk[x] == rnk[y]) stk[++top] = make_pair(x, ++rnk[x]); 
    } 
    void Undo(int cur) {
    	while (top > cur) { 
    		pair<int, int> pre = stk[top--]; 
    		fa[pre.first] = pre.first; 
    		rnk[pre.first] = pre.second; 
    	} 
    } 
    #define lson (o << 1) 
    #define rson (o << 1 | 1) 
    void modify(int o, int l, int r, int ql, int qr, int pos) { 
    	if (ql <= l && r <= qr) return (void)vec[o].push_back(pos);
    	int mid = (l + r) >> 1; 
    	if (ql <= mid) modify(lson, l, mid, ql, qr, pos); 
    	if (qr > mid) modify(rson, mid + 1, r, ql, qr, pos); 
    } 
    void Div(int o, int lval, int rval, int st, int ed) { 
    	if (st > ed) return ;
    	int cur = top;
    	for (int i = 0, l = vec[o].size(); i < l; i++) unite(p[vec[o][i]].x, p[vec[o][i]].y); 
    	if (lval == rval) {
    		for (int i = st; i <= ed; i++) 
    	    	ans[q[i].id] = getf(q[i].x) == getf(q[i].y);
    		return ; 
    	} 
    	int mid = (lval + rval) >> 1, lt = 0, rt = 0; 
    	for (int i = st; i <= ed; i++) 
    		if (q[i].t <= mid) lq[++lt] = q[i]; 
    		else rq[++rt] = q[i]; 
    	for (int i = 1; i <= lt; i++) q[st + i - 1] = lq[i]; 
    	for (int i = 1; i <= rt; i++) q[st + i + lt - 1] = rq[i]; 
    	Div(lson, lval, mid, st, st + lt - 1); 
        Div(rson, mid + 1, rval, st + lt, ed);
    	Undo(cur); 
    }
    int cnt1, cnt2; 
    int main () {
    	N = gi(), M = gi();
    	for (int i = 1; i <= N; i++) fa[i] = i, rnk[i] = 1; 
    	for (int i = 1; i <= M; i++) { 
    		int op = gi(), x = gi(), y = gi(); 
    	     if (x > y) swap(x, y); 
    		 if (op == 0) tim[x][y] = i; 
    		 if (op == 1) modify(1, 1, M, tim[x][y], i, ++cnt1), p[cnt1] = (Modify){x, y}, tim[x][y] = 0; 
    		 if (op == 2) q[++cnt2] = (Query){x, y, i, cnt2}; 
    	} 
    	for (int i = 1; i <= N; i++)
    		for (int j = i; j <= N; j++) 
    			if (tim[i][j]) modify(1, 1, M, tim[i][j], M, ++cnt1), p[cnt1] = (Modify){i, j}; 
    	Div(1, 1, M, 1, cnt2); 
    	for (int i = 1; i <= cnt2; i++) ans[i] ? puts("Y") : puts("N"); 
    	return 0; 
    } 
    
  • 相关阅读:
    十步完全理解 SQL
    Oracle VM Virtual
    Pycharm 使用
    Open Yale course:Listening to Music
    SQL 必知必会
    安装 SQL server 2008 R2
    Ubuntu安装mysql之后,编译找不到头文件
    core dump文件的生成
    Linux静态库与动态库制作过程
    GEC6818连接Ubuntu,下载程序至开发板
  • 原文地址:https://www.cnblogs.com/heyujun/p/10325249.html
Copyright © 2011-2022 走看看