[JLOI2015]城池攻占

[JLOI2015]城池攻占

题目

小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池。这 n 个城池用 1 到 n 的整数表示。除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi <i。也就是说,所有城池构成了一棵有根树。这 m 个骑士用 1 到 m 的整数表示,其中第 i 个骑士的初始战斗力为 si,第一个攻击的城池为 ci。每个城池有一个防御值 hi,如果一个骑士的战斗力大于等于城池的生命值,那么骑士就可以占领这座城池;否则占领失败,骑士将在这座城池牺牲。占领一个城池以后,骑士的战斗力将发生变化,然后继续攻击管辖这座城池的城池,直到占领 1 号城池,或牺牲为止。除 1 号城池外,每个城池 i 会给出一个战斗力变化参数 ai;vi。若 ai =0,攻占城池 i 以后骑士战斗力会增加 vi;若 ai =1,攻占城池 i 以后,战斗力会乘以 vi。注意每个骑士是单独计算的。也就是说一个骑士攻击一座城池,不管结果如何,均不会影响其他骑士攻击这座城池的结果。现在的问题是,对于每个城池,输出有多少个骑士在这里牺牲;对于每个骑士,输出他攻占的城池数量。

INPUT

第 1 行包含两个正整数 n;m,表示城池的数量和骑士的数量。第 2 行包含 n 个整数,其中第 i 个数为 hi,表示城池 i 的防御值。第 3 到 n +1 行,每行包含三个整数。其中第 i +1 行的三个数为 fi;ai;vi,分别表示管辖这座城池的城池编号和两个战斗力变化参数。第 n +2 到 n + m +1 行,每行包含两个整数。其中第 n + i 行的两个数为 si;ci,分别表示初始战斗力和第一个攻击的城池。

OUTPUT

输出 n + m 行,每行包含一个非负整数。其中前 n 行分别表示在城池 1 到 n 牺牲的骑士数量,后 m 行分别表示骑士 1 到 m 攻占的城池数量。

SAMPLE

INPUT

5 5

50 20 10 10 30

1 1 2

2 0 5

2 0 -10

1 0 10

20 2

10 3

40 4

20 4

35 5

OUTPUT

2

2

0

0

0

1

1

3

1

1

解题报告

左偏树首题

首先,我们发现,我们需要维护所有骑士战斗力的最小值,不断判断他们是否会被杀死,所以很容易想到用小根堆来维护,但是,我们还需要不断维护从儿子节点传来的信息,所以我们需要可合并堆——左偏树,至于修改操作,可以类比线段树的$lazy$思想,打上标记并$pushdown$下去即可

YY了一下午的左偏树啊qwq

结果左偏树没打错啊qwq

错的是树上$bfs$啊qwq

根本不能$bfs$啊qwq

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 typedef long long L;
  6 inline L read(){
  7     L sum(0),f(1);char ch(getchar());
  8     for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
  9     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
 10     return sum*f;
 11 }
 12 #define get_dis(x) (x?x->dis:-1)
 13 struct node{
 14     node *lch,*rch;
 15     L key,add,mul;
 16     int id,dis;
 17     node(L v=0,int x=0):lch(NULL),rch(NULL),key(v),add(0),mul(1),id(x),dis(0){}
 18     inline void pushdown(){
 19         if(add||mul^1){
 20             if(this->lch){
 21                 this->lch->key=this->lch->key*this->mul+this->add;
 22                 this->lch->add=this->lch->add*this->mul+this->add;
 23                 this->lch->mul*=this->mul;
 24             }
 25             if(this->rch){
 26                 this->rch->key=this->rch->key*this->mul+this->add;
 27                 this->rch->add=this->rch->add*this->mul+this->add;
 28                 this->rch->mul*=this->mul;
 29             }
 30             this->add=0;this->mul=1;
 31         }
 32     }
 33     inline void fixdis(){
 34         if(get_dis(this->lch)<get_dis(this->rch))
 35             swap(this->lch,this->rch);
 36         this->dis=get_dis(this->rch)+1;
 37     }
 38 }*heap[300005];
 39 struct edge{
 40     int e;
 41     edge *n;
 42 }*pre[300005];
 43 inline void insert(int s,int e){
 44     edge *tmp(new edge);
 45     tmp->e=e;tmp->n=pre[s];pre[s]=tmp;
 46 }
 47 int n,m,dep[300005],fa[300005],c[300005],kill[300005],att[300005],du[300005];
 48 int que[300005],head,tail;
 49 L h[300005],a[300005],v[300005];
 50 bool vis[300005];
 51 inline node* merge(node *&x,node *&y){
 52     if(!x)return y;if(!y)return x;//cout<<x<<' '<<x->rch<<' '<<y<<endl;
 53     if(x->key>y->key)swap(x,y);
 54     x->pushdown();x->rch=merge(x->rch,y);x->fixdis();return x;
 55 }
 56 inline void insert(node *&x,L v,int id){
 57     node *tmp(new node(v,id));
 58     x=merge(x,tmp);
 59 }
 60 inline node* pop(node *&x){
 61     if(!x)return NULL;x->pushdown();
 62     return merge(x->lch,x->rch);
 63 }
 64 inline void add(node *&x,L v){
 65     if(!x)return;
 66     x->pushdown();
 67     x->add+=v;
 68     x->key+=v;
 69 }
 70 inline void mul(node *&x,L v){
 71     if(!x)return;
 72     x->pushdown();
 73     x->mul*=v;
 74     x->key*=v;
 75 }
 76 int main(){
 77     freopen("fall.in","r",stdin);freopen("fall.out","w",stdout);
 78     n=read(),m=read();
 79     for(int i=1;i<=n;++i)
 80         h[i]=read();
 81     for(int i=2;i<=n;++i)
 82         fa[i]=read(),a[i]=read(),v[i]=read(),insert(fa[i],i),++du[fa[i]];
 83     que[++tail]=1;dep[1]=1;
 84     while(head<tail){
 85         int k(que[++head]);
 86         for(edge *i=pre[k];i;i=i->n){
 87             dep[i->e]=dep[k]+1;
 88             que[++tail]=i->e;
 89         }
 90     }
 91     for(int i=1;i<=m;++i){
 92         L x(read());c[i]=read();
 93         insert(heap[c[i]],x,i);
 94     }
 95     for(int k=n;k>=1;--k){
 96         while(heap[k]&&h[k]>heap[k]->key){
 97             ++kill[k];
 98             att[heap[k]->id]=dep[c[heap[k]->id]]-dep[k];
 99             heap[k]=pop(heap[k]);
100         }
101         if(heap[k]){
102             if(a[k]==0)
103                 add(heap[k],v[k]);
104             else
105                 mul(heap[k],v[k]);
106         }
107         if(fa[k]){
108             heap[fa[k]]=merge(heap[fa[k]],heap[k]);
109             if(!vis[fa[k]]){
110                 vis[fa[k]]=1;
111                 que[++tail]=fa[k];
112             }
113         }
114     }
115     while(heap[1]){
116         att[heap[1]->id]=dep[c[heap[1]->id]];
117         heap[1]=pop(heap[1]);
118     }
119     for(int i=1;i<=n;++i)printf("%d
",kill[i]);
120     for(int i=1;i<=m;++i)printf("%d
",att[i]);
121 }
View Code
原文地址:https://www.cnblogs.com/hzoi-mafia/p/7773541.html