P3261 [JLOI2015]城池攻占 可并堆

题意:

戳这里

分析:

又是一道巨佬秒切了的题

我们以每个城市作为一个小根堆,把骑士作为元素,每次弹出不符合的元素之后

向自己的 (fa) 进行合并,同时更新堆内的每一个元素

注意特判堆是否为空

代码:

#include<bits/stdc++.h>
#define lc t[rt].ls
#define rc t[rt].rs
#define pb push_back
using namespace std;

namespace zzc
{
    long long read()
    {
        long long x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
        return x*f;
    }

    const int maxn = 3e5+5;
    long long n,m,cnt;
    long long ans1[maxn],ans2[maxn],dep[maxn];
    vector<long long> g[maxn],h[maxn];

    struct city
    {
        long long opt,val,def,rt;
    }c[maxn];

    struct node
    {
        long long frm,ls,rs,val,tag,mul,dis;
    }t[maxn];

    void pushdown(int rt)
    {
        t[lc].val=(t[lc].val*t[rt].mul+t[rt].tag);
        t[rc].val=(t[rc].val*t[rt].mul+t[rt].tag);
        t[lc].mul=(t[lc].mul*t[rt].mul);
        t[rc].mul=(t[rc].mul*t[rt].mul);
        t[lc].tag=(t[lc].tag*t[rt].mul+t[rt].tag);
        t[rc].tag=(t[rc].tag*t[rt].mul+t[rt].tag);
        t[rt].tag=0;
        t[rt].mul=1;
    }

    int merge(int x,int y)
    {
        if(!x||!y) return x|y;
        if(t[x].val>t[y].val)  swap(x,y);
        pushdown(x);
        t[x].rs=merge(t[x].rs,y);
        if(t[t[x].rs].dis>t[t[x].ls].dis) swap(t[x].ls,t[x].rs);
        t[x].dis=t[t[x].rs].dis+1;
        return x;
    }
    
    int pop(int rt,int id)
    {
        ans1[rt]=id;
        pushdown(rt);
        return merge(lc,rc);
    }

    void work()
    {
        long long x;
        n=read();m=read();
        for(int i=1;i<=n;i++) c[i].def=read();
        for(int i=2;i<=n;i++) x=read(),h[x].pb(i),c[i].opt=read(),c[i].val=read();
        for(int i=1;i<=m;i++) t[i].val=read(),x=read(),g[x].pb(i),t[i].frm=x,t[i].mul=1,t[i].tag=0;
        for(int i=n;i>=1;i--)
        {
            for(auto j:g[i]) c[i].rt=merge(c[i].rt,j);
            for(auto j:h[i]) c[i].rt=merge(c[i].rt,c[j].rt);
            while(c[i].rt&&t[c[i].rt].val<c[i].def) c[i].rt=pop(c[i].rt,i);
            if(!c[i].opt)
            {
                t[c[i].rt].val+=c[i].val;
                t[c[i].rt].tag+=c[i].val;
            }
            else
            {
                t[c[i].rt].val*=c[i].val;
                t[c[i].rt].mul*=c[i].val;
                t[c[i].rt].tag*=c[i].val;
            }
        }
        dep[1]=1;
        for(int i=1;i<=n;i++) for(auto j:h[i]) dep[j]=dep[i]+1;
        for(int i=1;i<=m;i++) ans2[ans1[i]]++;
        for(int i=1;i<=n;i++) printf("%lld
",ans2[i]);
        for(int i=1;i<=m;i++) printf("%lld
",dep[t[i].frm]-dep[ans1[i]]);
    }



}

int main()
{
//	freopen("fall1.in","r",stdin);
    zzc::work();
    return 0;
}
原文地址:https://www.cnblogs.com/youth518/p/14236313.html