zoukankan      html  css  js  c++  java
  • BZOJ 4003 JLOI2015 城池攻占

    做法和APIO2012派遣 那道题目类似

    在树上DFS,维护当前子树的小根堆

    因为需要合并孩子们的信息,使用左偏树就可以了

    每次弹出死亡骑士,对剩余骑士打上奖励标记

    至于标记的下传和更改,只需要每次在需要遍历到这个点之前push_down就可以了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
     
    typedef long long LL;
    const int maxn=300010;
    int n,m;
    int a[maxn],rt[maxn],fa[maxn],c[maxn];
    int ans1[maxn],ans2[maxn];
    LL f[maxn],k[maxn],b[maxn],s[maxn];
    int h[maxn],cnt=0;
    int dep[maxn];
    struct edge{
        int to,next;
    }G[maxn];
    struct Tree{
        int L,R,dis;
        LL v,k,b;
    }t[maxn];
    void add(int x,int y){++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;}
    void Get_mark(int a,LL k,LL b){
        if(a==0)return;
        t[a].v=t[a].v*k+b;
        t[a].k*=k;t[a].b*=k;t[a].b+=b;
    }
    void push_down(int a){
        Get_mark(t[a].L,t[a].k,t[a].b);
        Get_mark(t[a].R,t[a].k,t[a].b);
        t[a].k=1;t[a].b=0;
    }
    int merge(int a,int b){
        if(!a||!b)return a+b;
        push_down(a);push_down(b);
        if(t[a].v>t[b].v)swap(a,b);
        t[a].R=merge(t[a].R,b);
        if(t[t[a].R].dis>t[t[a].L].dis)swap(t[a].L,t[a].R);
        t[a].dis=t[t[a].R].dis+1;
        return a;
    }
    void DFS(int u){
        for(int i=h[u];i;i=G[i].next){
            int v=G[i].to;
            dep[v]=dep[u]+1;
            DFS(v);
            Get_mark(rt[v],k[v],b[v]);
            rt[u]=merge(rt[u],rt[v]);
        }
        while(rt[u]&&t[rt[u]].v<f[u]){
            push_down(rt[u]);ans1[u]++;
            ans2[rt[u]]=dep[c[rt[u]]]-dep[u];
            rt[u]=merge(t[rt[u]].L,t[rt[u]].R);
        }return;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)scanf("%lld",&f[i]);
        for(int i=2;i<=n;++i){
            scanf("%d%lld%lld",&fa[i],&k[i],&b[i]);
            if(k[i]==0)k[i]=1;
            else k[i]=b[i],b[i]=0;
            add(fa[i],i);
        }
        for(int i=1;i<=m;++i){
            scanf("%lld%d",&s[i],&c[i]);
            t[i].v=s[i];t[i].k=1;t[i].b=0;
            rt[c[i]]=merge(rt[c[i]],i);
        }
        DFS(1);
        while(rt[1]){
            push_down(rt[1]);
            ans2[rt[1]]=dep[c[rt[1]]]+1;
            rt[1]=merge(t[rt[1]].L,t[rt[1]].R);
        }
        for(int i=1;i<=n;++i)printf("%d
    ",ans1[i]);
        for(int i=1;i<=m;++i)printf("%d
    ",ans2[i]);
        return 0;
         
    }
    

      

  • 相关阅读:
    Android实战经验之图像处理及特效处理的集锦(总结版)
    Android类似于滚动的通知栏实现
    Python概览
    高效程序员的45个习惯读书笔记
    Web前台传对象字符串到后台并让后台反序列化对象字符串的方法(ASP.NET)
    发布订阅者模式之C#委托实现
    表数据复制(迁移)
    Code Smell
    Python学习过程遇到的Bug不断更新
    Resharper 7小技巧系列:导航、书签、和最近编辑
  • 原文地址:https://www.cnblogs.com/joyouth/p/5392563.html
Copyright © 2011-2022 走看看