其他分享
首页 > 其他分享> > luoguP3261 [JLOI2015]城池攻占

luoguP3261 [JLOI2015]城池攻占

作者:互联网

题意

暴力自然是模拟,考虑优化下模拟的过程。

我们对每个点开个左偏树,初始为在该点的骑士,之后dfs过程当中从儿子向父亲合并,同时弹出小于当前点的骑士,增加当前点的答。对于每个骑士的答案,我们记录他的起始点和终点即可。

code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=300010;
int n,m,cnt;
int head[maxn],def[maxn],type[maxn],delta[maxn],ans1[maxn],ans2[maxn],root[maxn],dep[maxn],st[maxn];
struct edge{int to,nxt;}e[maxn<<1];
struct Heap
{
    #define lc(p) (heap[p].lc)
    #define rc(p) (heap[p].rc)
    #define val(p)(heap[p].val)
    #define dis(p) (heap[p].dis)
    #define tag1(p) (heap[p].tag1)
    #define tag2(p) (heap[p].tag2) 
    int lc,rc;
    int val,dis,tag1,tag2; 
}heap[maxn];
inline int read()
{
    char c=getchar();int res=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    return res*f;
}
inline void add(int u,int v)
{
    e[++cnt].nxt=head[u];
    head[u]=cnt;
    e[cnt].to=v;
}
inline void move(int x,int mul,int add)
{
    if(!x)return;
    val(x)*=mul;val(x)+=add;
    tag1(x)*=mul;tag2(x)*=mul;tag2(x)+=add;
}
inline void down(int x)
{
    move(lc(x),tag1(x),tag2(x)),move(rc(x),tag1(x),tag2(x));
    tag1(x)=1,tag2(x)=0;
}
int merge(int x,int y)
{
    if(!x||!y)return x+y;
    down(x),down(y);
    if(val(x)>val(y))swap(x,y);
    rc(x)=merge(rc(x),y);
    if(dis(rc(x))>dis(lc(x)))swap(lc(x),rc(x));
    dis(x)=dis(rc(x))+1;
    return x;
}
void dfs(int x,int pre)
{
    dep[x]=dep[pre]+1;
    for(int i=head[x];i;i=e[i].nxt)if(e[i].to!=pre)dfs(e[i].to,x),root[x]=merge(root[x],root[e[i].to]);
    while(root[x]&&val(root[x])<def[x])
    {
        down(root[x]);
        ans1[x]++;ans2[root[x]]=dep[st[root[x]]]-dep[x];
        root[x]=merge(lc(root[x]),rc(root[x]));
    }
    if(type[x])move(root[x],delta[x],0);
    else move(root[x],1,delta[x]);
}
signed main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)def[i]=read();
    for(int i=2;i<=n;i++)
    {
        int x=read();add(i,x),add(x,i);
        type[i]=read(),delta[i]=read();
    }
    dis(0)=-1;
    for(int i=1;i<=m;i++)tag1(i)=1;
    for(int i=1;i<=m;i++)
    {
        int k=read();st[i]=read();
        val(i)=k;
        root[st[i]]=merge(root[st[i]],i);
    }
    dfs(1,0);
    while(root[1])down(root[1]),ans2[root[1]]=dep[st[root[1]]],root[1]=merge(lc(root[1]),rc(root[1]));
    for(int i=1;i<=n;i++)printf("%lld\n",ans1[i]);
    for(int i=1;i<=m;i++)printf("%lld\n",ans2[i]);
    return 0;
}

标签:pre,JLOI2015,城池,int,maxn,rc,luoguP3261,root,dis
来源: https://www.cnblogs.com/nofind/p/11984747.html