zoukankan      html  css  js  c++  java
  • 【Luogu P5787】二分图 /【模板】线段树分治

    链接:

    洛谷

    题目大意:

    有一个 (n) 个节点的图,在 (k) 时间内有 (m) 条边会出现后消失,要求出每一时间段内这个图是否是二分图。

    思路:

    线段树分治用于离线、可撤销类的题目。

    线段树维护某时间内连的边。统计答案时,用扩展域并查集查询连边是否合法。并查集不可路径压缩,因为要用栈回溯。

    代码:

    const int N = 3e5 + 10;
    
    inline ll Read()
    {
    	ll x = 0, f = 1;
    	char c = getchar();
    	while (c != '-' && (c < '0' || c > '9')) c = getchar();
    	if (c == '-') f = -f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
    	return x * f;
    }
    
    int n, m, k;
    
    struct node
    {
    	int l, r, st, ed;
    }e[N];
    
    vector <int> t[N << 3];
    void Modify(int p, int l, int r, int L, int R, int id)
    {
    	if (l > R || r < L)  return;
    	if (L <= l && r <= R) 
    	{
    		t[p].push_back(id);
    		return;
    	}
    	int mid = l + r >> 1;
    	Modify (p << 1, l, mid, L, R, id);
    	Modify (p << 1 | 1, mid + 1, r, L, R, id);
    }
    
    struct Stack
    {
    	int x, y, add;
    };
    int top = 0;
    Stack stk[N << 2];
    
    int fa[N << 1], height[N << 1];
    
    int Find(int k) {return k == fa[k]? k: fa[k] = Find(fa[k]);} 
    void Merge (int u, int v)
    {
    	int x = Find(u), y = Find(v);
    	if (height[x] > height[y]) x ^= y ^= x ^= y;
    	stk[++top] = (Stack){x, y, height[x] == height[y]};
    	fa[x] = y;
    	if(height[x] == height[y]) height[y]++;
    }
    
    void Solve (int p, int l, int r)
    {
    	int flag = 1, lsttop = top;
    	for (int i = 0; i < t[p].size(); i++)
    	{	
    	int u = e[t[p][i]].l, v = e[t[p][i]].r;
    		int x = Find(u), y = Find(v);
    		if (x == y)
    		{
    			for (int j = l; j <= r; j++)
    				printf ("No
    ");
    			flag = 0;
    			break;
    		}
    		Merge (u, v + n);
    		Merge (v, u + n);
    	} 
    	if (flag)
    	{
    		if (l == r) printf ("Yes
    ");
    		else 
    		{
    			int mid = l + r >> 1;
    			Solve (p << 1, l, mid);
    			Solve (p << 1 | 1, mid + 1, r);
    		}
    	}
    	for (; top > lsttop; top--)
    		height[fa[stk[top].x]] -= stk[top].add,
    		fa[stk[top].x] = stk[top].x;
    }
    
    int main()
    {
    	n = Read(), m = Read(), k = Read();
    	int cnt = 0;
    	for (int i = 1; i <= m; i++)
    	{
    		e[i].l = Read(), e[i].r = Read(), e[i].st = Read(), e[i].ed = Read();
    		Modify(1, 1, k, e[i].st + 1, e[i].ed, i);
    	}
    	for (int i = 0; i <= n * 2; i++) fa[i] = i, height[i] = 1;
    	Solve (1, 1, k);
    	return 0;
    }
    
  • 相关阅读:
    UVA 401 回文词
    n的阶乘分解成素数幂的积
    DSSM问答匹配模型
    Enhanced LSTM for Natural Language Inference
    Bidirectional LSTM-CRF Models for Sequence Tagging
    Attention Is All You Need 学习笔记
    BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
    C++学习笔记(四)
    C++学习笔记(三)
    java学习笔记(七)
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/15138968.html
Copyright © 2011-2022 走看看