zoukankan      html  css  js  c++  java
  • BZOJ4003: [JLOI2015]城池攻占

    Description

    小铭铭最近获得了一副新的桌游,游戏中需要用 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

    Sample Output

    2
    2
    0
    0
    0
    1
    1
    3
    1
    1

    HINT

     对于 100% 的数据,1 <= n;m <= 300000; 1 <= fi<i; 1 <= ci <= n; -10^18 <= hi,vi,si <= 10^18;ai等于1或者2;当 ai =1 时,vi > 0;保证任何时候骑士战斗力值的绝对值不超过 10^18。

    这题不一看就是什么神仙数据结构么。。  点个技能点:左偏树(看个概念

    考虑暴力做法,对于每一个骑士往上比较,复杂度(nm)

    再考虑优化暴力,对于每个骑士,像线段树一样维护标记,往上跳,然后对于同一个节点的所有骑士,组成一颗类似主席树的东西

    往上跳的时候合并一下即可

    //MT_LI
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    ll def[310000];
    struct node{
        int x,y,next;
    }a[610000];int len,last[310000];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    struct heap{
        int lc,rc,d;
        ll c,mul,add;
    }tr[610000];
    int st[310000];
    int n,m,rt[310000];
    int tot[310000],die[310000];
    int fa[310000],op[310000];
    ll v[310000],dep[310000];
    void pushdown(int x)
    {
        int lc=tr[x].lc,rc=tr[x].rc;
        if(lc)
        {
            tr[lc].c=tr[lc].c*tr[x].mul+tr[x].add;
            tr[lc].add=tr[lc].add*tr[x].mul+tr[x].add;
            tr[lc].mul=tr[lc].mul*tr[x].mul;
        }
        if(rc)
        {
            tr[rc].c=tr[rc].c*tr[x].mul+tr[x].add;
            tr[rc].add=tr[rc].add*tr[x].mul+tr[x].add;
            tr[rc].mul=tr[rc].mul*tr[x].mul;
        }
        tr[x].mul=1;tr[x].add=0;
    }
    int merge(int x,int y)
    {
        if(x==0||y==0)return x+y;
        pushdown(x);pushdown(y);
        if(tr[x].c>tr[y].c)swap(x,y);
        tr[x].rc=merge(tr[x].rc,y);
        if(tr[tr[x].lc].d<tr[tr[x].rc].d)swap(tr[x].lc,tr[x].rc);
        tr[x].d=tr[tr[x].rc].d+1;
        return x;
    }
    void del(int x){rt[x]=merge(tr[rt[x]].lc,tr[rt[x]].rc);}
    void pre_tree_node(int x)
    {
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            fa[y]=x;dep[y]=dep[x]+1;
            pre_tree_node(y);
            rt[x]=merge(rt[x],rt[y]);
        }
        while(rt[x]&&tr[rt[x]].c<def[x])
        {
            tot[x]++;
            pushdown(rt[x]);
            die[rt[x]]=x;
            del(x);
        }
        if(op[x])
        {
            int now=rt[x];
            tr[now].c=tr[now].c*v[x];
            tr[now].mul=tr[now].mul*v[x];
            tr[now].add=tr[now].add*v[x];
        }
        else
        {
            int now=rt[x];
            tr[now].c=tr[now].c+v[x];
            tr[now].add=tr[now].add+v[x];
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=n;i++)scanf("%lld",&def[i]);
        for(int i=2;i<=n;i++)
        {
            scanf("%d%d%lld",&fa[i],&op[i],&v[i]);
            ins(fa[i],i);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%lld%d",&tr[i].c,&st[i]);tr[i].mul=1,tr[i].add=0;
            rt[st[i]]=merge(rt[st[i]],i);
        }
        dep[1]=1;fa[1]=0;pre_tree_node(1);
        for(int i=1;i<=n;i++)printf("%d
    ",tot[i]);
        for(int i=1;i<=m;i++)printf("%d
    ",dep[st[i]]-dep[die[i]]);
        return 0;
    }
  • 相关阅读:
    List of the best open source software applications
    Owin对Asp.net Web的扩展
    NSwag给api加上说明
    'workspace' in VS Code
    unable to find valid certification path to requested target
    JMeter的下载以及安装使用
    exception disappear when forgot to await an async method
    Filter execute order in asp.net web api
    记录web api的request以及response(即写log)
    asp.net web api的源码
  • 原文地址:https://www.cnblogs.com/MT-LI/p/9861505.html
Copyright © 2011-2022 走看看