1. 程式人生 > >luogu3261 [JLOI2015]城池攻佔

luogu3261 [JLOI2015]城池攻佔

目錄

題目

luogu
原來左偏樹真的能懶惰下放
這篇部落格應該要咕咕了
一開始我按照那篇部落格想了一下,感覺emm,還是瞄了一眼看到了pushdown

思路

類似線段樹2的pushdown,不過是套在了左偏樹
其他也就沒啥了
ans1直接刪除統計
ans2就初始深度-死亡深度(樹的路徑唯一嘛)
ps:深度可以在dfs的時候順便求出來
就這樣

錯誤&&反思

一開始20,死活不對
最後又是手賤n寫成m
還是20
又經過漫長debug(不會造樹data的傷感)
無奈去看題解,長著差不多的模樣
最後

 while(val[rt[u]] < fangyu[u] && rt[u]) {
        pushdown(rt[u]);
        ans2[rt[u]]=dep[S[rt[u]]]-dep[u];
        ans1[u]++;
        rt[u]=merge(ch[rt[u]][0],ch[rt[u]][1]);
}

居然一個pushdown就OK了
我想著是merge就會pushdown的,就沒寫、、、、

程式碼

#include <iostream>
#include <cstdio>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=3e5+7;
typedef long long ll;
inline ll read() {
    ll x=0,f=1;char s=getchar();
    for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
struct node {
    int v,nxt;
}e[maxn];
int head[maxn],tot;
void add_edge(int u,int v) {
    e[++tot].v=v;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int n,m,cnt,rt[maxn],ch[maxn][2],dis[maxn],ans1[maxn],ans2[maxn],dep[maxn];
ll A[maxn],B[maxn],fangyu[maxn],ad[maxn],mu[maxn],val[maxn];
void da_tag(int x,ll a,ll b) {
    val[x]=val[x]*a+b;
    ad[x]=ad[x]*a+b;
    mu[x]*=a;
}
void pushdown(int x) {
    if(ad[x]==0&&mu[x]==1) return;
    int it_a=ch[x][0],it_b=ch[x][1];
    da_tag(it_a,mu[x],ad[x]);
    da_tag(it_b,mu[x],ad[x]);
    ad[x]=0,mu[x]=1;
}
int merge(int x,int y) {
    if(!x || !y) return x+y;
    pushdown(x),pushdown(y);
    if(val[x]>val[y]) swap(x,y);
    ch[x][1]=merge(ch[x][1],y);
    if(dis[ch[x][0]]<dis[ch[x][1]]) swap(ch[x][0],ch[x][1]);
    dis[x]=dis[ch[x][1]]+1;
    return x;
}
int S[maxn];
int dfs(int u,int f) {
    dep[u]=dep[f]+1;
    for(int i=head[u];i;i=e[i].nxt) {
        int tmp=dfs(e[i].v,u);
        rt[u]=merge(rt[u],tmp);
    }
    while(val[rt[u]] < fangyu[u] && rt[u]) {
        pushdown(rt[u]);
        ans2[rt[u]]=u;
        ans1[u]++;
        rt[u]=merge(ch[rt[u]][0],ch[rt[u]][1]);
    }
    da_tag(rt[u],A[u],B[u]);
    return rt[u];
}
int main() {
    n=read(),m=read();
    FOR(i,1,m) mu[i]=1;
    FOR(i,1,n) fangyu[i]=read();
    FOR(i,2,n) {
        int x=read(),y=read();
        add_edge(x,i);
        A[i]=1;
        if(y) A[i]=read();
        else B[i]=read();
    }
    FOR(i,1,m) {
        ll x=read();S[i]=read();
        val[i]=x;
        rt[S[i]]=merge(rt[S[i]],i);
    }
    dfs(1,0);
    FOR(i,1,n) cout<<ans1[i]<<"\n";
    FOR(i,1,m) cout<<dep[S[i]]-dep[ans2[i]]<<"\n";
    return 0;
}