zoukankan      html  css  js  c++  java
  • BZOJ 4003 左偏树

    思路:
    用到了左偏树合并复杂度是logn的性质

    一开始先BFS一遍
    打标记的左偏树

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 600050
    #define int long long
    int n,m,h[N],fa[N],a[N],v[N],deep[N],s[N],c[N],root[N],vis[N];
    int q[N],head,tail,ver[N],next[N],first[N],tot,ans[N],num[N];
    struct Tree{int l,r,w,d,num,mul,add;}tr[N];
    void add(int x,int y){ver[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void BFS(){
        q[0]=1;
        while(head<=tail){
            int t=q[head++];
            for(int i=first[t];~i;i=next[i]){
                deep[ver[i]]=deep[t]+1;
                q[++tail]=ver[i];
            }
        }
    }
    void push_down(int x){
        int L=tr[x].l,R=tr[x].r;
        tr[L].w=tr[L].w*tr[x].mul+tr[x].add;
        tr[R].w=tr[R].w*tr[x].mul+tr[x].add;
        tr[L].add*=tr[x].mul,tr[L].mul*=tr[x].mul,tr[L].add+=tr[x].add;
        tr[R].add*=tr[x].mul,tr[R].mul*=tr[x].mul,tr[R].add+=tr[x].add;
        tr[x].add=0,tr[x].mul=1;
    }
    int merge(int k1,int k2){
        if(!k1||!k2)return k1+k2;
        push_down(k1),push_down(k2);
        if(tr[k1].w>tr[k2].w)swap(k1,k2);
        tr[k1].r=merge(tr[k1].r,k2);
        if(tr[tr[k1].l].d<tr[tr[k1].r].d)swap(tr[k1].l,tr[k1].r);
        tr[k1].d=tr[tr[k1].r].d+1;
        return k1;
    }
    void del(int &x){
        push_down(x);
        int L=tr[x].l,R=tr[x].r;
        x=merge(L,R);
    }
    signed main(){
        memset(first,-1,sizeof(first));
        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]);
            add(fa[i],i),tr[i].mul=1;
        }BFS();
        for(int i=1;i<=m;i++){
            scanf("%lld%lld",&s[i],&c[i]);
            tr[i].w=s[i],tr[i].num=i;
            root[c[i]]=merge(root[c[i]],i);
        }
        for(int i=tail;i>=0;i--){
            while(root[q[i]]&&tr[root[q[i]]].w<h[q[i]]){
                ans[tr[root[q[i]]].num]=deep[c[tr[root[q[i]]].num]]-deep[q[i]];
                vis[tr[root[q[i]]].num]=1;
                del(root[q[i]]);
                num[q[i]]++;
            }
            push_down(root[q[i]]);
            if(a[q[i]])tr[root[q[i]]].mul*=v[q[i]],tr[root[q[i]]].w=tr[root[q[i]]].w*v[q[i]];
            else tr[root[q[i]]].add+=v[q[i]],tr[root[q[i]]].w=tr[root[q[i]]].w+v[q[i]];
            root[fa[q[i]]]=merge(root[fa[q[i]]],root[q[i]]);
        }
        for(int i=1;i<=m;i++)if(!vis[i])ans[i]=deep[c[i]]+1;
        for(int i=1;i<=n;i++)printf("%lld
    ",num[i]);
        for(int i=1;i<=m;i++)printf("%lld
    ",ans[i]);
    }

    这里写图片描述

  • 相关阅读:
    瀑布流
    轮播图
    封装动画的函数
    回到顶部带动画
    动画setInterval
    模拟滚动条
    放大镜
    刷新
    cookie
    拖拽
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532146.html
Copyright © 2011-2022 走看看