zoukankan      html  css  js  c++  java
  • LuoGuP3261:[JLOI2015]城池攻占

    Pre

    这道题难度不是很大,也不重要,大佬请不要浪费时间。

    Solution

    对于每一个节点深搜,合并每个节点上面没死掉的士兵,当然包括这个节点自己上面的,然后取这当中(val)小的,如果小于这个节点的要求,就死掉。

    至于懒标记的使用,和洛谷的线段树2模板一样。

    Code

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std; 
    const int N = 300000 + 5;
    struct Graph {
        int fr[N], to[N], h[N], tot;
        inline void add (int u, int v) {
            tot++;
            fr[tot] = h[u];
            to[tot] = v;
            h[u] = tot;
        }
    }gg;
    struct Heap {
        int fa[N], ch[N][2], dis[N];
        ll tags[N], tagm[N], val[N];
        inline int Find (int u) {return fa[u] == u ? u : fa[u] = Find (fa[u]);}
        inline void push_down (int p) {
            if (tagm[p] != 1) {
                val[p] *= tagm[p];
                
                tags[ch[p][0]] *= tagm[p];
                tagm[ch[p][0]] *= tagm[p];
                tags[ch[p][1]] *= tagm[p];
                tagm[ch[p][1]] *= tagm[p];
                tagm[p] = 1;
            }
            if (tags[p]) {
                val[p] += tags[p];
                
                tags[ch[p][0]] += tags[p];
                tags[ch[p][1]] += tags[p];
                tags[p] = 0;
            }
        }
        inline int merge (int u, int v) {
            if (u == v) {return u;}
            if (!u || !v) {return u + v;}
            push_down (u), push_down (v);
            if (val[u] > val[v]) {swap (u, v);}
            ch[u][1] = merge (ch[u][1], v);
            fa[ch[u][1]] = u;
            if (dis[ch[u][1]] > dis[ch[u][0]]) {swap (ch[u][0], ch[u][1]);}
            dis[u] = dis[ch[u][1]] + 1;
            return u;
        }
        inline void del (int p) {
            p = Find (p);
            push_down (p);
            ch[p][0] = merge (ch[p][0], ch[p][1]);
            fa[ch[p][0]] = ch[p][0];
            fa[p] = ch[p][0];
            ch[p][0] = ch[p][1] = 0;
        }
    }uu;
    struct Tmp {
        int p, des;
        Tmp (int x = 0, int y = 0) {
            p = x, des = y;
        }
    }info[N];
    int n, m, a[N], cnt[N], ans[N], dep[N], id[N], suf[N];
    ll h[N], v[N];
    inline void dfs (int u, int f) {
        dep[u] = dep[f] + 1;
        for (int i = gg.h[u]; i; i = gg.fr[i]) {
            dfs (gg.to[i], u);
            if (id[u]) {
                int x = uu.Find(id[u]), y = uu.Find(id[gg.to[i]]);
                id[u] = uu.merge(x, y);
            }
            else {
                id[u] = id[gg.to[i]];
            }
        }
        if (id[u]) {
            int now = uu.Find (id[u]);
            uu.push_down(now);
            while (uu.val[now] < h[u]) {
                cnt[u]++;
                ans[now] = u;
                int tmp = uu.ch[now][0] ? uu.ch[now][0] : uu.ch[now][1];
                uu.del (now);
                now = uu.Find (tmp);
                if (!now) {break;}
                uu.push_down(now);
            }
            id[u] = now = uu.Find (now);
            if (u == 1) {
                return ;
            }
            if (a[u]) {
                uu.tagm[now] *= v[u];
                uu.tags[now] *= v[u];
            }
            else {
                uu.tags[now] += v[u];
            }
        }
    }
    inline void init () {
        for (int i = 1; i <= m; ++i) {
            if (i != 1 && info[i].des == info[i - 1].des) {
                int u = uu.Find(info[i].p) , v = uu.Find(info[i - 1].p);
                uu.merge (u, v);
            }
            else {
                id[info[i].des] = info[i].p;
            }
        }
    }
    int main () {
        memset (ans, -1, sizeof (ans));
        scanf ("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i) {scanf ("%lld", &h[i]);}
        for (int i = 2; i <= n; ++i) {
            int f;
            scanf ("%d%d%lld", &f, &a[i], &v[i]);
            gg.add(f, i);
        }
        for (int i = 1; i <= m; ++i) {
            uu.fa[i] = i;
            uu.tagm[i] = 1;
            int c;
            scanf ("%lld%d", &uu.val[i], &c);
            suf[i] = c;
            info[i] = Tmp (i, c);
        }
        sort (info + 1, info + m + 1, [](Tmp m, Tmp n) {return m.des < n.des;});
        init ();
        dfs (1, 0);
        for (int i = 1; i <= n; ++i) {printf ("%d
    ", cnt[i]);}
        for (int i = 1; i <= m; ++i) {
            printf ("%d
    ", dep[suf[i]] - dep[ans[i]]);
        }
        return 0;
    }
    

    Conclusion

    猛然发现结构体还是很好用的。

    其次是维护乘(&)加的标记的操作有必要熟悉一下,还有之前的一些常用的技巧。

  • 相关阅读:
    Codeforces Round #613 选讲
    Codeforces Round #612 选讲
    Codeforces917E
    一道题20
    LOJ#2244. 「NOI2014」起床困难综合症
    求欧拉回路
    *LOJ#2134. 「NOI2015」小园丁与老司机
    vim操作命令
    常见问题解决
    CentOS7下如何修改mysql的数据目录
  • 原文地址:https://www.cnblogs.com/ChiTongZ/p/11241231.html
Copyright © 2011-2022 走看看