• [JLOI2015]城池攻占 可并堆


    题目传送门

    难得遇到一个不卡常的,,

    维护一个小根堆,堆里是当前有的骑士,按dfs序,所有不能攻占该城市的都弹出,城市阻挡人数++,这个人攻占的城市=depth[出生城市]-depth[该城市];然后把可以攻占的加标记和乘标记更新后再向上合并到它的父节点。所以,我们需要一个支持合并的小根堆。左偏堆板子一套,美滋滋。然后,成功把根攻占的骑士攻占城市数=depth[出生城市]。然后直接输出即可。

    最多m次合并,每次最多带n个人,O(mn);初始插入O(mlogm),每个人最多弹1次,O(mlogm)。综上,就是O(mn+mlogm)。

    代码,,一如既往地丑,,

    #include<bits/stdc++.h>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<list>
    #include<set>
    #include<vector>
    #include<iostream>
    #define ll long long
    #define re register
    #define inf 0x7f7f7ff
    #define inl inline
    #define sqr(x) (x*x)
    //#define eps 1e-8
    #define debug printf("debug
    ");
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#pragma GCC optimize (2)
    //#pragma G++ optimize (2)
    using namespace std;
    //const ll mod;
    const ll MAXN=3e5+10;
    inl ll read() {
        re ll x = 0; re int f = 1;
        char ch = getchar();
        while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }
        while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x * f;
    }
    inl char readc() {
        char ch=getchar();
        while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar();
        return ch;
    }
    inl void write(re ll x){
        if(x>=10)write(x/10);
        putchar(x%10+'0');
    }
    inl void writeln(re ll x){
        if(x<0) {x=-x;putchar('-');}
        write(x); puts("");
    }
    inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
    inl ll Lcm(re ll a,re ll b) {return a/gcd(a,b)*b;}
    inl void FR() {
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    }
    inl void FC() {
        fclose(stdin);
        fclose(stdout);
    }
    struct Node {
        ll ls,rs,dis,val;
        ll add,mul;
    }Tree[MAXN];
    inl void cov(ll x,ll add,ll mul) {
        Tree[x].val*=mul;Tree[x].val+=add;
        Tree[x].add*=mul;Tree[x].mul*=mul;Tree[x].add+=add;
    }
    inl void pushdown(ll x) {
        cov(Tree[x].ls,Tree[x].add,Tree[x].mul);
        cov(Tree[x].rs,Tree[x].add,Tree[x].mul);
        Tree[x].add=0;Tree[x].mul=1;
    }
    ll merge(ll a,ll b) {
        if(!a||!b) return a^b;
        pushdown(a),pushdown(b);
        if(Tree[a].val>Tree[b].val) swap(a,b);
        Tree[a].rs=merge(Tree[a].rs,b);
        if(Tree[Tree[a].ls].dis<Tree[Tree[a].rs].dis) swap(Tree[a].ls,Tree[a].rs);
        Tree[a].dis=Tree[Tree[a].rs].dis+1;
        return a;
    }
    ll n,m,cnt,head[MAXN],h[MAXN],depth[MAXN];
    ll rt[MAXN],a[MAXN],v[MAXN],c[MAXN],ans[2][MAXN];
    struct edge {
        ll u,v,nxt;
    }e[MAXN];
    inl void adde(ll u,ll v) {
        e[++cnt].u=u;e[cnt].v=v;
        e[cnt].nxt=head[u];head[u]=cnt;
    }
    void dfs(ll x,ll fa) {
        for(re ll hs=head[x];hs;hs=e[hs].nxt) {
            re ll sv=e[hs].v;
            depth[sv]=depth[x]+1;
            dfs(sv,x);rt[x]=merge(rt[x],rt[sv]);
        }
        while(rt[x]&&Tree[rt[x]].val<h[x]) {
            pushdown(rt[x]);
            ++ans[0][x];ans[1][rt[x]]=depth[c[rt[x]]]-depth[x];
            rt[x]=merge(Tree[rt[x]].ls,Tree[rt[x]].rs);
        }
        if(a[x]) cov(rt[x],0,v[x]);
        else cov(rt[x],v[x],1);
    }
    int main() {
    //  FR();
          n=read(),m=read();
          for(re ll i=1;i<=n;i++) h[i]=read();
          for(re ll i=2;i<=n;i++) {
              re ll f=read();adde(f,i);
              a[i]=read(),v[i]=read();
        }
        for(re ll i=1;i<=m;i++) {
            Tree[i].val=read(),c[i]=read();
            Tree[i].mul=1;rt[c[i]]=merge(rt[c[i]],i);
        }
        depth[1]=1;dfs(1,0);
        while(rt[1]) {
            pushdown(rt[1]);ans[1][rt[1]]=depth[c[rt[1]]];
            rt[1]=merge(Tree[rt[1]].ls,Tree[rt[1]].rs);
        }
        for(re ll i=1;i<=n;i++) writeln(ans[0][i]);
        for(re ll i=1;i<=m;i++) writeln(ans[1][i]);
    //  FC();
        return 0;
    }
  • 相关阅读:
    linux下文件夹的创建、复制、剪切、重命名、清空和删除命令
    Linux 删除文件夹和创建文件的命令
    linux下拷贝整个目录
    星云大师:这十句话 我受用一生
    dex
    瘋耔java语言笔记
    VCC_VID_VTT等的含义
    一位数码管引脚
    android从应用到驱动之—camera(2)---cameraHAL的实现
    android从应用到驱动之—camera(1)---程序调用流程[转]
  • 原文地址:https://www.cnblogs.com/20020723YJX/p/9470835.html
Copyright © 2020-2023  润新知