洛谷3261,可并堆打标记

这题网上题解到处都是。
但有一个关键处


void dfs(int x,int fa){
    dep[x]=dep[fa]+1;
    for(int i=h[x];i;i=e[i].next){
        int y=e[i].to;
        dfs(y,x);
        r[x]=merge(r[x],r[y]);
    }
    while(r[x] && a[r[x]].v<hh[x]){
        ++ans1[x];
        ans2[r[x]]=dep[c[r[x]]]-dep[x];
        pop(r[x]);
    }
    if(aa[x] && r[x])cov(r[x],vv[x],0);
        else cov(r[x],1,vv[x]);
}
void dfs(int x,int fa){
    dep[x]=dep[fa]+1;
    for(int i=h[x];i;i=e[i].next){
        int y=e[i].to;
        dfs(y,x);
        while(r[x] && a[r[x]].v<hh[x]){
            ++ans1[x];
            ans2[r[x]]=dep[c[r[x]]]-dep[x];
            pop(r[x]);
        }
        r[x]=merge(r[x],r[y]);
    }
    if(aa[x] && r[x])cov(r[x],vv[x],0);
        else cov(r[x],1,vv[x]);
}

这两份代码那个对哪个错?答案是第一个对。因为第二个会让叶子结点的骑士活下来(鸣谢ww140142)

#pra\
gma GCC optimize("O2")
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1000005;
int xb,r[maxn],h[maxn],n,m,i,c[maxn],ans1[maxn],ans2[maxn],dep[maxn],aa[maxn],y;
LL hh[maxn],vv[maxn],s[maxn],x;
struct node{
    int l,r,d;
    LL ch,ji,v;//cheng,jia
    node(LL _v=0):v(_v){
        l=r=d=ji=0;
        ch=1;
    }
    bool operator>(const node&rhs){
        return v>rhs.v;
    }
    bool operator<(const node&rhs){
        return v<rhs.v;
    }
}a[maxn];
void cov(int i,LL x,LL y){
    if(!i)return;
    a[i].v*=x;
    a[i].v+=y;
    a[i].ch*=x;
    a[i].ji*=x;
    a[i].ji+=y;
}
void pushdown(int i){
    cov(a[i].l,a[i].ch,a[i].ji);
    cov(a[i].r,a[i].ch,a[i].ji);
    a[i].ch=1;
    a[i].ji=0;
}
int merge(int x,int y){
    if(!x || !y)return x|y;
    pushdown(x);
    pushdown(y);
    if(a[x]>a[y])swap(x,y);
    a[x].r=merge(a[x].r,y);
    if(a[a[x].r].d>a[a[x].l].d)swap(a[x].l,a[x].r);
    if(a[x].r)a[x].d=a[a[x].r].d+1;
        else a[x].d=0;
    return x;
}
struct edge{
    int to,next;
    edge(int _to=0,int _next=0):to(_to),next(_next){}
}e[maxn];
void addedge(int x,int y){
    e[++xb]=edge(y,h[x]);
    h[x]=xb;
}
void pop(int&x){
    pushdown(x);
    x=merge(a[x].l,a[x].r);
}
void dfs(int x,int fa){
    dep[x]=dep[fa]+1;
    for(int i=h[x];i;i=e[i].next){
        int y=e[i].to;
        dfs(y,x);
        r[x]=merge(r[x],r[y]);
    }
    while(r[x] && a[r[x]].v<hh[x]){
        ++ans1[x];
        ans2[r[x]]=dep[c[r[x]]]-dep[x];
        pop(r[x]);
    }
    if(aa[x] && r[x])cov(r[x],vv[x],0);
        else cov(r[x],1,vv[x]);
}
inline int getint(){
    int x=0,y=1;
    char c=getchar();
    while(!isdigit(c)){
        if(c=='-')y=-1;
        c=getchar();
    }
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return x*y;
}
inline LL getl(){
    LL x=0,y=1;
    char c=getchar();
    while(!isdigit(c)){
        if(c=='-')y=-1;
        c=getchar();
    }
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return x*y;
}
int buf[100];
inline void putint(int x){
    if(!x)putchar('0');
        else{
            int xb=0;
            for(;x;x/=10)buf[++xb]=x%10;
            for(;xb;--xb)putchar(buf[xb]+48);
        }
}
int main(){
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i)hh[i]=getl();
    for(i=2;i<=n;++i){
        y=getint();
        aa[i]=getint();
        vv[i]=getl();
        addedge(y,i);
    }
    for(i=1;i<=m;++i){
        x=getl();
        c[i]=getint();
        a[i]=node(x);
        r[c[i]]=merge(r[c[i]],i);
    }
    dfs(1,0);
    while(r[1]){
        ans2[r[1]]=dep[c[r[1]]];
        pop(r[1]);
    }
    for(i=1;i<=n;++i)putint(ans1[i]),putchar('\n');
    for(i=1;i<=m;++i)putint(ans2[i]),putchar('\n');
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值