BZOJ 4003 左偏树

来源:互联网 发布:秒装软件下载 编辑:程序博客网 时间:2024/06/09 21:33

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

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

//By SiriusRen#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 600050#define int long longint 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]);}

这里写图片描述

0 0
原创粉丝点击