zoukankan      html  css  js  c++  java
  • 【bzoj4551】[Tjoi2016&Heoi2016]树

    *题目描述:
    在2016年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树(根为1),有以下
    两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个
    结点,可以打多次标记。)2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖
    先)你能帮帮他吗?
    *输入:
    输入第一行两个正整数N和Q分别表示节点个数和操作次数接下来N-1行,每行两个正整数u,v(1≤u,v≤n)表示u到v
    有一条有向边接下来Q行,形如“opernum”oper为“C”时表示这是一个标记操作,oper为“Q”时表示这是一个询
    问操作对于每次询问操作,1 ≤ N, Q ≤ 100000。
    *输出:
    输出一个正整数,表示结果
    *样例输入:
    5 5
    1 2
    1 3
    2 4
    2 5
    Q 2
    C 2
    Q 2
    Q 5
    Q 3
    *样例输出:
    1
    2
    2
    1
    *题解:
    我们将操作离线处理,然后从下往上做,我们用并查集来维护这棵树(森林)的形态,在读入操作时把打标记的点和它父亲断开,并且给这个点的标记数量+1。我们倒过来操作时,如果是询问,答案就是此时并查集的Find,如果是修改,就将标记-1,如果标记等于0的话就把自己和它的父亲的集合并起来,然后就做完啦。
    *代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    #ifdef WIN32
        #define LL "%I64d"
    #else
        #define LL "%lld"
    #endif
    
    #ifdef CT
        #define debug(...) printf(__VA_ARGS__)
        #define setfile() 
    #else
        #define debug(...)
        #define filename ""
        #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
    #endif
    
    #define R register
    #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
    #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    char B[1 << 15], *S = B, *T = B;
    inline int FastIn()
    {
        R char ch; R int cnt = 0; R bool minus = 0;
        while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
        ch == '-' ? minus = 1 : cnt = ch - '0';
        while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
        return minus ? -cnt : cnt;
    }
    #define maxn 100010
    int fa[maxn], Fa[maxn], ans[maxn], cnt[maxn];
    struct Poi
    {
        int opt, x, id;
    }qq[maxn];
    inline int Find(R int x)
    {
        return Fa[x] == x ? x : Fa[x] = Find(Fa[x]);
    }
    int main()
    {
    //  setfile();
        R int n = FastIn(), q = FastIn();
        Fa[1] = cnt[1] = 1;
        for (R int i = 1; i < n; ++i)
        {
            R int a = FastIn(), b = FastIn();
            fa[b] = Fa[b] = a;
        }
        R int qcnt = 0;
        for (R int i = 1; i <= q; ++i)
        {
            R char opt = getc();
            while (opt < 'A' || opt > 'Z') opt = getc();
            R int x = FastIn();
            qq[i].x = x;
            qq[i].opt = opt == 'Q';
            if (opt == 'Q') qq[i].id = ++qcnt;
            else Fa[x] = x, ++cnt[x];
        }
        for (R int i = q; i; --i)
        {
            if (qq[i].opt)
                ans[qq[i].id] = Find(qq[i].x);
            else
            {
                --cnt[qq[i].x];
                if (!cnt[qq[i].x]) Fa[qq[i].x] = fa[qq[i].x];
            }
        }
        for (R int i = 1; i <= qcnt; ++i) printf("%d
    ", ans[i] );
        return 0;
    }
  • 相关阅读:
    dom4j 解析 xml文件1
    java 简单的动态代理例子
    标识接口的作用 (转)
    JAVA servlet输出IE6下乱码
    java时间操作函数汇总
    IE支持getElementsByClassName方法
    女朋友问我 LB 是谁?
    人类高质量 Java 学习路线【一条龙版】
    程序员作图工具和技巧,你 get 了么?
    3 分钟了解 JSON Schema
  • 原文地址:https://www.cnblogs.com/cocottt/p/6765008.html
Copyright © 2011-2022 走看看