zoukankan      html  css  js  c++  java
  • Luogu 3261 [JLOI2015]城池攻占

    BZOJ 4003

    需要实现一个可并堆。

    每个点维护一个小根堆,然后一开始把所有骑士加入到它所在的点的小根堆当中,实际上空间是$O(m)$的,然后我们从上到下不断合并这个小根堆,合并完之后如果遇到堆顶小于当前城市的防御值就弹掉堆顶顺便记录答案。

    对于那些攻占掉城池对骑士的贡献的处理,可以采用打标记的方式实现,在合并的时候$down$一下就好了。注意$down$要写在$merge$函数的最上面,因为有一些点还没有下传标记就被$merge$掉了。

    要注意弹出堆顶元素之前要先$down$一下 。

    最后在清空一下第一个堆中的元素就好了。

    不会算时间复杂度$QωQ$。

    Code:

    // luogu-judger-enable-o2
    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int N = 3e5 + 5;
    
    int n, m, tot = 0, head[N], type[N], dep[N], ans[N];
    ll def[N], rat[N];
    
    struct Knight {
        int pos, ed; 
        ll atk;
    } a[N];
    
    struct Edge {
        int to, nxt;
    } e[N << 1];
    
    inline void add(int from, int to) {
        e[++tot].to = to;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    } 
    
    template <typename T>
    inline void swap(T &x, T &y) {
        T t = x; x = y; y = t;
    }
    
    namespace LeftlistTree {
        struct Node {
            int lc, rc, dis, id;
            ll key, mulTag, addTag;
        } s[N];
        
        #define lc(p) s[p].lc
        #define rc(p) s[p].rc
        #define key(p) s[p].key
        #define mulTag(p) s[p].mulTag
        #define addTag(p) s[p].addTag
        #define dis(p) s[p].dis
        #define id(p) s[p].id 
        
        int root[N], nodeCnt = 0;
        
        inline int newNode(int p) {
            ++nodeCnt;
            lc(nodeCnt) = rc(nodeCnt) = 0;
            dis(nodeCnt) = 0;
            id(nodeCnt) = p;
            key(nodeCnt) = a[p].atk;
            addTag(nodeCnt) = 0LL, mulTag(nodeCnt) = 1LL;
            return nodeCnt;
        }
        
        inline void down(int p) {
            if(!p) return;
            if(mulTag(p) != 1) {
                if(lc(p)) {
                    key(lc(p)) *= mulTag(p);
                    addTag(lc(p)) *= mulTag(p);
                    mulTag(lc(p)) *= mulTag(p);            
                }
                
                if(rc(p)) {
                    key(rc(p)) *= mulTag(p);
                    addTag(rc(p)) *= mulTag(p);
                    mulTag(rc(p)) *= mulTag(p);            
                } 
                
                mulTag(p) = 1;
            }
            
            if(addTag(p) != 0) {
                if(lc(p)) {
                    key(lc(p)) += addTag(p);
                    addTag(lc(p)) += addTag(p);            
                }
                
                if(rc(p)) {
                    key(rc(p)) += addTag(p);
                    addTag(rc(p)) += addTag(p);    
                }
                
                addTag(p) = 0; 
            }
        }
        
        int merge(int x, int y) {
            down(x), down(y);
            if(!x || !y) return x + y;
            if(key(x) > key(y)) swap(x, y);
            rc(x) = merge(rc(x), y);
            
            if(dis(lc(x)) < dis(rc(x))) swap(lc(x), rc(x));
            dis(x) = dis(rc(x)) + 1;
            return x;
        }
        
    } using namespace LeftlistTree;
    
    void solve(int x, int fat, int depth) {
        dep[x] = depth;
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            solve(y, x, depth + 1);
            
            root[x] = merge(root[x], root[y]);
        }
        
        for(; root[x] && key(root[x]) < def[x]; ) {
            ++ans[x];
            a[id(root[x])].ed = x;
            down(root[x]);
            root[x] = merge(lc(root[x]), rc(root[x]));
        }
        
        if(root[x]) {
            if(!type[x]) {
                key(root[x]) += rat[x];
                addTag(root[x]) += rat[x];
            } else {
                key(root[x]) *= rat[x];
                mulTag(root[x]) *= rat[x];
                addTag(root[x]) *= rat[x];
            }
        }
    }
    
    int main() {
    //    freopen("3.in", "r", stdin);
    //    freopen("my.out", "w", stdout);
        
        read(n), read(m);
        for(int i = 1; i <= n; i++) read(def[i]);
        for(int fat, i = 2; i <= n; i++) {
            read(fat);
            add(fat, i), add(i, fat);
            read(type[i]), read(rat[i]);
        }
        for(int i = 1; i <= m; i++) {
            read(a[i].atk), read(a[i].pos);
            root[a[i].pos] = merge(root[a[i].pos], newNode(i));
        }
        
        solve(1, 0, 1);
        
        for(int i = 1; i <= n; i++)
            printf("%d
    ", ans[i]);
        
        for(; root[1]; ) {
            a[id(root[1])].ed = 0;
            down(root[1]);
            root[1] = merge(lc(root[1]), rc(root[1]));
        }
        
        for(int i = 1; i <= m; i++)    
            printf("%d
    ", dep[a[i].pos] - dep[a[i].ed]);
        
        return 0;
    }
    View Code
  • 相关阅读:
    硬件设计问题——持续更新
    PCB设计资源整理
    PCB层叠设计和电源分割
    PCB设计技巧
    铜厚电流、Layout 3W原则 20H原则 五五原则
    final关键字
    面向对象——继承与组合
    面向对象——继承
    this总结
    static总结
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9858714.html
Copyright © 2011-2022 走看看