码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ4003][JLOI2015]城池攻占

时间:2018-02-23 13:35:17      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:gpo   cpp   int   href   cst   logs   pac   return   markdown   

BZOJ
Luogu

sol

左偏树
骑士对于树上结点挂链,每次合并所有子树上的骑士后把所有攻击力小于城池防御值的骑士弹掉。
左偏树维护加乘懒标记
记得要pushdown
delete的时候也要记得pushdown!

code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const int MAX=300005;
struct edge{int to,next;}a[MAX],b[MAX];
int head[MAX],cnt,ft[MAX];
bool type[MAX];
ll h[MAX],key[MAX],v[MAX],plu[MAX],mul[MAX];
int n,m,ls[MAX],rs[MAX],dis[MAX],str[MAX],dep[MAX],dead[MAX],up[MAX];
ll gi()
{
    ll x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=-1,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*w;
}
void cover(int A,ll c,ll j)
{
    if (!A) return;
    key[A]*=c;key[A]+=j;
    mul[A]*=c;plu[A]*=c;plu[A]+=j;
}
void pushdown(int A)
{
    cover(ls[A],mul[A],plu[A]);
    cover(rs[A],mul[A],plu[A]);
    mul[A]=1;plu[A]=0;
}
int merge(int A,int B)
{
    if (!A||!B) return A+B;
    if (key[A]>key[B]) swap(A,B);
    pushdown(A);pushdown(B);
    rs[A]=merge(rs[A],B);
    if (dis[ls[A]]<dis[rs[A]]) swap(ls[A],rs[A]);
    dis[A]=dis[rs[A]]+1;
    return A;
}
int del(int A)
{
    pushdown(A);
    return merge(ls[A],rs[A]);
}
int dfs(int u,int f)
{
    dep[u]=dep[f]+1;
    int A=0,B;
    for (int e=ft[u];e;e=b[e].next) A=merge(A,b[e].to);
    for (int e=head[u];e;e=a[e].next)
    {
        int v=a[e].to;
        B=dfs(v,u);
        A=merge(A,B);
    }
    while (key[A]<h[u]&&A)
    {
        up[A]=dep[u];++dead[u];
        A=del(A);
    }
    if (type[u]) cover(A,v[u],0);
    else cover(A,1,v[u]);
    return A;
}
int main()
{
    n=gi();m=gi();
    for (int i=1;i<=n;i++) h[i]=gi();
    for (int i=2,u;i<=n;i++)
    {
        u=gi();
        a[++cnt]=(edge){i,head[u]};head[u]=cnt;
        type[i]=gi();v[i]=gi();
    }
    cnt=0;
    for (int i=1;i<=m;i++)
    {
        key[i]=gi();str[i]=gi();
        b[++cnt]=(edge){i,ft[str[i]]};ft[str[i]]=cnt;
    }
    dfs(1,0);
    for (int i=1;i<=n;i++) printf("%d\n",dead[i]);
    for (int j=1;j<=m;j++) printf("%d\n",dep[str[j]]-up[j]);
    return 0;
}

[BZOJ4003][JLOI2015]城池攻占

标签:gpo   cpp   int   href   cst   logs   pac   return   markdown   

原文地址:https://www.cnblogs.com/zhoushuyu/p/8461464.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!