zoukankan      html  css  js  c++  java
  • 洛谷:P3950 部落冲突

    原题地址:https://www.luogu.org/problemnew/show/P3950

    题目简述

    给定一棵树,每次给定一个操作,有如下两种:

    1. 将某条边染黑
      2.询问给定的u,v两点间是否有边被染黑

    思路

    询问两点间是否有边被染黑只需要在求LCA时判一下就行。所以直接上树链剖分即可。
    本题不需要使用线段树,使用树状数组查询路径上是否有任意一段区间和不为0即可。


    代码

    #include <bits/stdc++.h>
    #define lowbit(x) x&-x
    using namespace std;
    typedef pair<int, int> P;
    const int maxn = 1000000;
    P war[maxn];
    int fa[maxn], dep[maxn], val[maxn], sz[maxn], top[maxn], son[maxn];
    int tre[maxn];
    int tot;
    int cntw;
    int n, m;
    inline int read()
    {
        int ch, x = 0, f = 1;ch = getchar();
        while((ch < '0' || ch > '9') && ch != '-') ch = getchar();
        ch == '-' ? f = -1, ch = getchar() : 0;
        while(ch >= '0' && ch <= '9') {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return f * x;
    }
    struct Edge {
        int to, len, nxt;
        Edge() {}
        Edge(int _to, int _len, int _nxt):to(_to), len(_len), nxt(_nxt) {}
    }E[maxn];
    int h[maxn], cnte;
    int L[maxn], R[maxn];
    void update(int x, int add) {
        for(int i = x;i <= maxn; i += lowbit(i)) tre[i] += add;
    }
    int query(int x) {
        int ans = 0; for(int i = x; i; i -= lowbit(i)) ans += tre[i]; return ans;
    }
    inline void add_edge(int u, int v, int w) {
        E[++cnte] = Edge(v, w, h[u]), h[u] = cnte;
        E[++cnte] = Edge(u, w, h[v]), h[v] = cnte;
    }
    void dfs1(int x) {
    
        sz[x] = 1; dep[x] = dep[fa[x]] + 1;
        for(int i = h[x]; i; i = E[i].nxt) {
            int to = E[i].to;
            if(to == fa[x]) continue;
            fa[to] = x;val[x] = E[i].len;
            dfs1(to);
            sz[x] += sz[to];
            if(sz[to] > sz[son[x]]) son[x] = to;
        }
    
    }
    void dfs2(int x) {
        L[x] = ++tot;
        if(x == son[fa[x]]) top[x] = top[fa[x]];
        else top[x] = x;
        if(son[x]) dfs2(son[x]);
        for(int i = h[x]; i; i = E[i].nxt) {
            int to = E[i].to;
            if(to == fa[x] || to == son[x]) continue;
            dfs2(to);
        }
        R[x] = tot;
    }
    
    void cut(int x, int y) {
        if(L[x] < L[y]) swap(x, y);
        update(L[x], 1);
    }
    void connect(int x, int y) {
        if(L[x] < L[y]) swap(x, y);
        update(L[x], -1);
    }
    int qsum(int x, int y) {//其实可以查到有1就退出,不用查完和
        int ans = 0;
        while(top[x] != top[y])
        {
            if(dep[top[x]] < dep[top[y]])swap(x, y);
            ans += (query(L[x]) - query(L[top[x]] - 1));
            x = fa[top[x]];
        }
        if(dep[x] < dep[y])swap(x, y);
        if (x!=y)
    		ans += (query(L[x]) - query(L[y]));
        return ans;
    }
    signed main() {
        scanf("%d%d", &n, &m);
        for(int i = 1; i < n; i++) add_edge(read(), read(), 0);
        dfs1(1);
        dfs2(1);
        for(int i = 1;i <= m; i++) {
            char s[50];
            cin >> s;
            if(s[0] == 'C') {
                int u = read(), v = read();
                cut(u, v);
                war[++cntw] = P(u, v);
            } 
            else if(s[0] == 'U') {
                int w = read();
                connect(war[w].first, war[w].second);
            }
            else {
                if(qsum(read(), read()) != 0) puts("No");
                else puts("Yes");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    System 类的使用
    StringBuffer 与 StringBuilder类的使用
    String 类 的 使用
    多线程
    音乐播放
    数据库
    表示图编辑
    UITextView(2)
    UITextView
    tarBar
  • 原文地址:https://www.cnblogs.com/yyy2015c01/p/9839356.html
Copyright © 2011-2022 走看看