[BZOJ4003][JLOI2015]城池攻占

左偏树裸题 合并+lazytag即可

每个点合并儿子然后弹出所有<ci的即可

然后每个骑士直接dep[x]-dep[y]挂了的节点和初始节点的深度差即可

样例太水了注意要判每个节点万一骑士挂完了是空的QAQ

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
#define N 300010
using namespace std;
ll read()
{
    ll s=0,f=1; char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')    f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
struct edge{int to,lt;}e[N]; int in[N],cnt,dep[N]; int rt[N];
void add(int x,int y){e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;} 
struct node{ll val,mul,add; int fa,son[2],dis;}t[N];
int st[N]; int war[N],city[N]; ll v[N],c[N]; bool kd[N];
void pushdown(int x)
{
    int ls=t[x].son[0],rs=t[x].son[1]; ll mul=t[x].mul,add=t[x].add;
    if(mul!=1)
    {
        t[ls].val*=mul; t[rs].val*=mul; t[ls].mul*=mul; t[rs].mul*=mul; t[ls].add*=mul; t[rs].add*=mul;
        t[x].mul=1;
    }
    if(add)
    {
        t[ls].val+=add; t[rs].val+=add; t[ls].add+=add; t[rs].add+=add;
        t[x].add=0;
    }
}
int find(int x){return t[x].fa^x?t[x].fa=find(t[x].fa):x;}
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].son[1]=merge(t[x].son[1],y);
    t[t[x].son[1]].fa=t[t[x].son[0]].fa=x; t[x].fa=x;
    if(t[t[x].son[1]].dis>t[t[x].son[0]].dis)    swap(t[x].son[0],t[x].son[1]);
    t[x].dis=t[t[x].son[1]].dis+1;
    return x;
}
void modify(int x,ll add,ll mul)
{
    if(mul!=1){t[x].val*=mul; t[x].mul*=mul; t[x].add*=mul;}
    if(add){t[x].val+=add; t[x].add+=add;}
}
void pop(int &x,int ct)
{
    war[x]=dep[st[x]]-dep[ct]; city[ct]++; pushdown(x);
    t[t[x].son[0]].fa=t[x].son[0]; t[t[x].son[1]].fa=t[x].son[1];
    t[x].fa=merge(t[x].son[0],t[x].son[1]);
    t[t[x].fa].fa=t[x].fa; x=t[x].fa;
}
void work(int x)
{
    for(int i=in[x];i;i=e[i].lt)
        dep[e[i].to]=dep[x]+1,work(e[i].to),rt[x]=merge(rt[x],rt[e[i].to]);
    while(rt[x]&&t[rt[x]].val<c[x])    pop(rt[x],x);
    if(kd[x]) modify(rt[x],0,v[x]); else modify(rt[x],v[x],1);
}
int n,m;
int main()
{
    n=read(); m=read(); int fi,ci;
    for(int i=1;i<=n;i++)    c[i]=read();
    for(int i=2;i<=n;i++)    fi=read(),add(fi,i),kd[i]=read(),v[i]=read();
    for(int i=1;i<=m;i++)    t[i].val=read(),ci=read(),rt[ci]=merge(rt[ci],i),st[i]=ci;
    work(1); dep[0]=-1; while(rt[1])    pop(rt[1],0);
    for(int i=1;i<=n;i++)    printf("%d\n",city[i]);
    for(int i=1;i<=m;i++)    printf("%d\n",war[i]);
    return 0;
}
View Code

 

posted @ 2019-04-04 11:53  寒雨微凝  阅读(151)  评论(0编辑  收藏  举报