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\n",num[i]);
    for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
}

这里写图片描述

posted @ 2016-12-20 16:58  SiriusRen  阅读(215)  评论(0编辑  收藏  举报