思路

左偏树维护每个骑士的战斗力和加入的深度(因为只能向上跳)

注意做乘法的时候加法tag会受到影响

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
struct Node{
int lson,rson,dis,num,mul,add,add_dep,sz,fa,id;
}LT[300100];
int n,m,u[300100<<1],v[300100<<1],fir[300100],nxt[300100<<1],cnt,fa[300100],S[300100],C[300100],A[300100],V[300100],H[300100],root[300100],ans_city[300100],ans_man[300100],dep[300100];
int find(int x){
if(LT[x].fa==x)
return x;
else
return LT[x].fa=find(LT[x].fa);
}
void pushup(int o){
LT[o].sz=LT[LT[o].lson].sz+LT[LT[o].rson].sz+1;
}
void pushdown(int o){
if(LT[o].mul!=1){
LT[LT[o].lson].num*=LT[o].mul;
LT[LT[o].rson].num*=LT[o].mul;
LT[LT[o].lson].mul*=LT[o].mul;
LT[LT[o].rson].mul*=LT[o].mul;
LT[LT[o].lson].add*=LT[o].mul;
LT[LT[o].rson].add*=LT[o].mul;
LT[o].mul=1;
}
if(LT[o].add){
LT[LT[o].lson].num+=LT[o].add;
LT[LT[o].rson].num+=LT[o].add;
LT[LT[o].lson].add+=LT[o].add;
LT[LT[o].rson].add+=LT[o].add;
LT[o].add=0;
}
}
int merge(int x,int y){
if(x*y==0)
return x+y;
pushdown(x);
pushdown(y);
if(LT[x].num>LT[y].num)
swap(x,y);
LT[x].rson=merge(LT[x].rson,y);
if(LT[LT[x].lson].dis<LT[LT[x].rson].dis)
swap(LT[x].lson,LT[x].rson);
LT[x].dis=LT[LT[x].rson].dis+1;
LT[LT[x].lson].fa=LT[LT[x].rson].fa=LT[x].fa=x;
pushup(x);
return x;
}
int pop(int u){
pushdown(u);
LT[LT[u].lson].fa=LT[u].lson;
LT[LT[u].rson].fa=LT[u].rson;
return LT[u].fa=merge(LT[u].lson,LT[u].rson);
}
void addedge(int ui,int vi){
++cnt;
u[cnt]=ui;
v[cnt]=vi;
nxt[cnt]=fir[ui];
fir[ui]=cnt;
}
void dfs_dep(int u){
dep[u]=dep[fa[u]]+1;
for(int i=fir[u];i;i=nxt[i]){
if(v[i]==fa[u])
continue;
dfs_dep(v[i]);
}
}
void dfs(int u){
for(int i=fir[u];i;i=nxt[i]){
if(v[i]==fa[u])
continue;
dfs(v[i]);
root[u]=merge(root[u],root[v[i]]);
}
while(LT[root[u]].sz>=1&&LT[root[u]].num<H[u]){
ans_city[u]++;
ans_man[LT[root[u]].id]=LT[root[u]].add_dep-dep[u];
root[u]=pop(root[u]);
}
if(A[u]){
LT[root[u]].num*=V[u];
LT[root[u]].mul*=V[u];
LT[root[u]].add*=V[u];
}
else {
LT[root[u]].num+=V[u];
LT[root[u]].add+=V[u];
}
}
void init(void){
for(int i=1;i<=m;i++){
LT[i].add_dep=dep[C[i]];
LT[i].add=0;
LT[i].mul=1;
LT[i].id=i;
LT[i].dis=1;
LT[i].sz=1;
LT[i].lson=LT[i].rson=0;
LT[i].fa=i;
LT[i].num=S[i];
root[C[i]]=merge(root[C[i]],i);
}
}
signed main(){
scanf("%lld %lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&H[i]);
}
for(int i=2;i<=n;i++){
scanf("%lld %lld %lld",&fa[i],&A[i],&V[i]);
if(fa[i]){
addedge(i,fa[i]);
addedge(fa[i],i);
}
}
for(int i=1;i<=m;i++){
scanf("%lld %lld",&S[i],&C[i]);
}
dfs_dep(1);
init();
dfs(1);
while(LT[root[1]].sz>=1){
ans_man[LT[root[1]].id]=LT[root[1]].add_dep;
root[1]=pop(root[1]);
}
for(int i=1;i<=n;i++){
printf("%lld\n",ans_city[i]);
}
for(int i=1;i<=m;i++) {
printf("%lld\n",ans_man[i]);
}
return 0;
}

P3261 [JLOI2015]城池攻占的更多相关文章

  1. [洛谷P3261] [JLOI2015]城池攻占(左偏树)

    不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...

  2. 洛谷P3261 [JLOI2015]城池攻占(左偏树)

    传送门 每一个城市代表的点开一个小根堆,把每一个骑士合并到它开始攻占的城池所代表的点上 然后开始dfs,每一次把子树里那些还活着的骑士合并上来 然后再考虑当前点的堆,一直pop直到骑士全死光或者剩下的 ...

  3. P3261 [JLOI2015]城池攻占 题解

    题目 小铭铭最近获得了一副新的桌游,游戏中需要用 \(m\) 个骑士攻占 \(n\) 个城池.这 \(n\) 个城池用 \(1\) 到 \(n\) 的整数表示.除 \(1\) 号城池外,城池 \(i\ ...

  4. P3261 [JLOI2015]城池攻占 (左偏树+标记下传)

    左偏树还是满足堆的性质,节点距离就是离最近的外节点(无左或者右儿子  或者二者都没有)的距离,左偏性质就是一个节点左儿子的距离不小于右儿子,由此得:节点距离等于右儿子的距离+1. 本题就是对于每个节点 ...

  5. [洛谷P3261][JLOI2015]城池攻占

    题目大意:有$n$个点的树,第$i$个节点有一个权值$h_i$,$m$个骑士,第$i$个骑士攻击力为$v_i$,一个骑士可以把从它开始的连续的父亲中比它小的节点攻破,攻破一个节点可以把攻击力加或乘一个 ...

  6. BZOJ 4003 / Luogu P3261 [JLOI2015]城池攻占 (左偏树)

    左偏树裸题,在树上合并儿子传上来的堆,然后小于当前结点防御值的就pop掉,pop的时候统计答案. 修改的话就像平衡树一样打懒标记就行了. 具体见代码 CODE #include<bits/std ...

  7. BZOJ_4003_[JLOI2015]城池攻占_可并堆

    BZOJ_4003_[JLOI2015]城池攻占_可并堆 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 ...

  8. 【BZOJ4003】[JLOI2015]城池攻占 可并堆

    [BZOJ4003][JLOI2015]城池攻占 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号 ...

  9. [bzoj4003][JLOI2015]城池攻占_左偏树

    城池攻占 bzoj-4003 JLOI-2015 题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上.每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城 ...

随机推荐

  1. os.system

    python   os.system os.system()函数在不同的系统下可以实现不同的作用 一.window下: os.system("ping www.baidu.com" ...

  2. html5-css动画-2d

    div{    width: 300px;    height: 100px;    margin: 50px;    padding: 50px;    background: green;     ...

  3. 数据模型Model(I)

    枚举.结构体和协议组成Model //定义一个协议 protocol BaseItemProtocal { var title: String { get set } //属性是可读可写的 var t ...

  4. 使用Python中的config配置

    Python中有ConfigParser类,可以很方便的从配置文件中读取数据(如DB的配置,路径的配置),所以可以自己写一个函数,实现读取config配置. config文件的写法比较简单,[sect ...

  5. CBV源码解析

    1.CBV(class based view) 首先定义一个视图函数,用类的方式定义: 举例: class LoginView(View): def get(self,request): return ...

  6. python 使用json.dumps() 的indent 参数,获得漂亮的格式化字符串后输出

    想获得漂亮的格式化字符串后输出,可以使用json.dumps() 的indent 参数.它会使得输出和pprint() 函数效果类似 >>> data {'age': 4, 'nam ...

  7. c# ref和out参数

    向方法传递参的时候,对应的参数通常会用实参的拷贝来初始化.就是说随便在方法内部进行怎样的修改,都不会影响作为参数传递的变量的原始值. 通过上面的例子我们可以看出来,如果一个方法的参数是引用类型,那么使 ...

  8. AELF(ELF)区块链项目介绍

    AELF(ELF)区块链项目介绍,Aelf在交易所上的名称是ELF,最近涨了不少了,可以长期关注逢低建仓,根据自身情况可以适当轻仓配置点.AELF总结下来就是希望打造一个B2B的区块链开放式OS系统. ...

  9. 51Nod 2020 排序相减

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=2020 思路:排序 水水 #include<iostre ...

  10. AtCoder Beginner Contest 045 C - たくさんの数式 / Many Formulas

    Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement You are given a string ...