zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    JavaEE XML XSL转换(XSLT)
    Java 并发 中断线程
    Java 并发 线程同步
    Java 并发 关键字volatile
    Java 并发 线程的优先级
    Java 并发 线程属性
    Java 并发 线程的生命周期
    Java NIO Channel和Buffer
    Java NIO Channel之FileChannel [ 转载 ]
    VUE CLI3 less 全局变量引用
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7773541.html
Copyright © 2011-2022 走看看