「JLOI2015」城池攻占 可并堆

传送门

分析

如果直接暴力枚举的话肯定会超时
我们可以从下往上遍历,维护一个小根堆
每次到达一个节点把战败的骑士扔出去
剩下的再继续向上合并,注意要维护一下其实的战斗力
可以像线段树那样用一个lazy标记

代码

#include
using namespace std;
const int maxn=300005;
typedef long long ll;
ll head[maxn],tot=1;
struct asd{
    ll from,to,next,ty;
    ll val;
}b[maxn];
void ad(ll aa,ll bb,ll cc,ll dd){
    b[tot].from=aa;
    b[tot].to=bb;
    b[tot].ty=cc;
    b[tot].val=dd;
    b[tot].next=head[aa];
    head[aa]=tot++;
}
ll bjc[maxn],bjj[maxn],gjl[maxn];
ll lch[maxn],rch[maxn];
void push_down(ll xx){
    if(xx==0) return;
    if(bjc[xx]!=1){
        gjl[lch[xx]]*=bjc[xx],bjj[lch[xx]]*=bjc[xx],bjc[lch[xx]]*=bjc[xx];
        gjl[rch[xx]]*=bjc[xx],bjj[rch[xx]]*=bjc[xx],bjc[rch[xx]]*=bjc[xx];
        bjc[xx]=1;
    }
    if(bjj[xx]!=0){
        gjl[lch[xx]]+=bjj[xx],bjj[lch[xx]]+=bjj[xx];
        gjl[rch[xx]]+=bjj[xx],bjj[rch[xx]]+=bjj[xx];
        bjj[xx]=0;
    }
}
ll d[maxn],dep[maxn],rt[maxn];
ll h[maxn];
ll bing(ll xx,ll yy){
    if(!xx) return yy;
    if(!yy) return xx;
    push_down(xx),push_down(yy);
    if(gjl[xx]>gjl[yy]) swap(xx,yy);
    rch[xx]=bing(rch[xx],yy);
    if(d[lch[xx]]

你可能感兴趣的:(「JLOI2015」城池攻占 可并堆)