zoukankan      html  css  js  c++  java
  • [JLOI2015][左偏树] 城池攻占

    题目链接
    考虑每个节点建一个以骑士攻击力为关键字的小根堆,从叶子节点向上扫描,每次弹堆至堆顶骑士攻击力大于当前城池防御力,可以采用左偏树维护,
    对于城池的攻击力改变值,可以借用线段树区间修改的懒标记思想,打上乘法及加法标记,每次涉及到改变堆结构的操作前下放标记即可。

    稍微卡常之后可过

    代码

    # include <iostream>
    # include <cstdio>
    # define MAXN 300005
    
    struct edge{
    	int v, next;
    }e[MAXN];
    int hd[MAXN], cntE;
    struct heap{
    	int ls, rs, dis, rt;
    	long long tagA, tagM; // 乘标记,加标记 
    }hp[MAXN];
    struct knight{
    	long long pow;
    	int fir;
    }kn[MAXN];
    struct city{ 
    	int dep; // 深度
    	long long def; // 防御力
    	long long ai, vi; // 改变值
    }ct[MAXN];
    int death[MAXN], destory[MAXN];
    
    template<typename T>
    void rd(T & x);
    void AddE(int u, int v);
    void DFS(int now, int fa);
    int Merge(int x, int y);
    void PushDown(int now);
    void Calc(int now, long long mul, long long pls);
    // int Find(int x);
    
    int main(){
    	int n, m;
    	rd<int>(n), rd<int>(m);
    
    	hp[0].dis = -1;
    
    	for(int i = 1; i <= n; i++){
    		rd<long long>(ct[i].def);
    	}
    
    	for(int i = 2, tmp; i <= n; i++){
    		rd<int>(tmp), rd<long long>(ct[i].ai), rd<long long>(ct[i].vi);
    		AddE(tmp, i);
    	}
    
    	for(int i = 1; i <= m; i++){
    		rd<long long>(kn[i].pow), rd<int>(kn[i].fir);
    		hp[kn[i].fir].rt = Merge(hp[kn[i].fir].rt, i); // 注意每个位置可能不止一个士兵,所以不能直接将 rt 设为 i 而应该合并
    		hp[i].tagM = 1;
    	}
    
    	DFS(1, 0);
    
    	while(hp[1].rt){
    		PushDown(hp[1].rt);
    		destory[hp[1].rt] = ct[kn[hp[1].rt].fir].dep;
    
    		hp[1].rt = Merge(hp[hp[1].rt].ls, hp[hp[1].rt].rs);
    	}
    
    	for(int i = 1; i <= n; i++){
    		printf("%d
    ", death[i]);
    	}
    	for(int i = 1; i <= m; i++){
    		printf("%d
    ", destory[i]);
    	}
    
    	return 0;
    }
    
    // int Find(int x){
    // 	return hp[x].rt == x ? x : hp[x].rt = Find(hp[x].rt);
    // }
    
    void Calc(int now, long long mul, long long pls){
    	if(now){
    		(kn[now].pow *= mul) += pls;
    		hp[now].tagM *= mul;
    		(hp[now].tagA *= mul) += pls;
    	}
    }
    
    void PushDown(int now){
    	Calc(hp[now].ls, hp[now].tagM, hp[now].tagA);
    	Calc(hp[now].rs, hp[now].tagM, hp[now].tagA);
    	hp[now].tagM = 1, hp[now].tagA = 0;
    }
    
    int Merge(int x, int y){
    	if(!x || !y){
    		return x + y;
    	}
    
    	PushDown(x); PushDown(y);
    
    	if(kn[x].pow > kn[y].pow){
    		std::swap(x, y);
    	}
    
    	hp[x].rs = Merge(hp[x].rs, y);
    
    	if(hp[hp[x].ls].dis < hp[hp[x].rs].dis){
    		std::swap(hp[x].ls, hp[x].rs);
    	}
    	hp[x].dis = hp[hp[x].rs].dis + 1;
    
    	return x;
    }
    
    void DFS(int now, int fa){
    	ct[now].dep = ct[fa].dep + 1;
    	
    	for(int i = hd[now]; i; i = e[i].next){
    		DFS(e[i].v, now);
    		hp[now].rt = Merge(hp[now].rt, hp[e[i].v].rt);
    	}
    
    	while(hp[now].rt && kn[hp[now].rt].pow < ct[now].def){
    		PushDown(hp[now].rt);
    		death[now] += 1, destory[hp[now].rt] = ct[kn[hp[now].rt].fir].dep - ct[now].dep;
    		hp[now].rt = Merge(hp[hp[now].rt].ls, hp[hp[now].rt].rs);
    	}
    
    	if(ct[now].ai){
    		Calc(hp[now].rt, ct[now].vi, 0);
    	}
    	else{
    		Calc(hp[now].rt, 1, ct[now].vi);
    	}
    }
    
    void AddE(int u, int v){
    	e[++cntE].v = v, e[cntE].next = hd[u], hd[u] = cntE;
    }
    template<typename T>
    void rd(T & x){
    	x = 0; T fl = 1;
    	int ch = getchar();
    	for(	;!isdigit(ch); ch = getchar()){
    		if(ch == '-'){
    			fl = -1;
    		}
    	}
    	for(	; isdigit(ch); ch = getchar()){
    		x = x * 10 + ch - '0';
    	}
    	x *= fl;
    }
    
  • 相关阅读:
    Codeforces Round #717 (Div. 2)
    Codeforces Round #716 (Div. 2)
    atCoder Regular Contest 117
    Codeforces Round #715 (Div. 2)
    牛客挑战赛49
    从零开始搭建webpack应用
    扫盲:npm
    MYSQL安装
    Int和integer区别
    关于JDK配置以及DOS窗口执行指令
  • 原文地址:https://www.cnblogs.com/Foggy-Forest/p/13464049.html
Copyright © 2011-2022 走看看