BZOJ 4003 城池攻占

Posted on 2016-05-13 17:30  ziliuziliu  阅读(149)  评论(0编辑  收藏  举报

可并堆。打标记。

注意细节。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#define maxv 300500
#define maxe 300500
using namespace std;
struct edge
{
    long long v,nxt;
}e[maxe];
set <long long> s[maxv];
set <long long> ::iterator it;
long long n,m,h[maxv],fath[maxv],a[maxv],v[maxv],w[maxv],c[maxv],val[maxv];
long long tree[maxv][3],dfl[maxv],dis[maxv],nume=0,l1[maxv],l2[maxv];
long long ans1[maxv],ans2[maxv],top[maxv],g[maxv];
bool vis[maxv];
void addedge(long long u,long long v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void pushdown(long long x)
{
    long long ls=tree[x][1],rs=tree[x][2];
    l1[ls]=l1[ls]*l2[x]+l1[x];
    l1[rs]=l1[rs]*l2[x]+l1[x];
    l2[ls]*=l2[x];
    l2[rs]*=l2[x];
    val[ls]=val[ls]*l2[x]+l1[x];
    val[rs]=val[rs]*l2[x]+l1[x];
    l1[x]=0;l2[x]=1;
}
void pushup(long long x)
{
    long long ls=tree[x][1],rs=tree[x][2];
    if (dfl[ls]<dfl[rs]) swap(tree[x][1],tree[x][2]);
    if (rs==0) dfl[x]=0;
    else dfl[x]=dfl[rs]+1;
}
long long merge(long long a,long long b)
{
    if (a==0) return b;
    if (b==0) return a;
    if (val[a]>val[b]) swap(a,b);
    pushdown(a);
    tree[a][2]=merge(tree[a][2],b);
    pushup(a);
    return a;
}
long long pop(long long x)
{
    long long ls=tree[x][1],rs=tree[x][2];
    pushdown(x);
    tree[x][1]=0;tree[x][2]=0;
    return merge(ls,rs);
}
void dfs1(long long x)
{
    for (long long i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        dis[v]=dis[x]+1;
        dfs1(v);
    }
}
void dfs2(long long x)
{
    for (long long i=g[x];i;i=e[i].nxt)
        dfs2(e[i].v);
    long long root=-1;
    for (it=s[x].begin();it!=s[x].end();it++)
    {
        long long now=*it;
        if (root==-1) root=now;
        else root=merge(root,now);
    }
    for (long long i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        if (top[v]<=0) continue;
        if (root==-1) root=top[v];
        else root=merge(root,top[v]);
    }
    long long cnt=0;
    while ((val[root]<h[x]) && (root>=1))
    {
        ans2[root]=dis[c[root]]-dis[x];
        vis[root]=true;
        root=pop(root);
        cnt++;
    }    
    ans1[x]=cnt;
     if (a[x]==0) {l1[root]+=v[x];val[root]+=v[x];}
    else {l2[root]*=v[x];l1[root]*=v[x];val[root]*=v[x];}
     top[x]=root;
}
int main()
{
    memset(vis,false,sizeof(vis));
    scanf("%lld%lld",&n,&m);
    fill(l2+1,l2+m+1,1);
    for (long long i=1;i<=n;i++)
        scanf("%lld",&h[i]);
    for (long long i=2;i<=n;i++)
    {
        scanf("%lld%lld%lld",&fath[i],&a[i],&v[i]);
        addedge(fath[i],i);
    }
    for (long long i=1;i<=m;i++)
    {
        scanf("%lld%lld",&w[i],&c[i]);
        s[c[i]].insert(i);
        val[i]=w[i];
    }
    dfs1(1);
    dfs2(1);
    for (long long i=1;i<=n;i++) printf("%lld\n",ans1[i]);
    for (long long i=1;i<=m;i++)
    {
        if ((ans2[i]==0) && (vis[i]==false)) printf("%lld\n",dis[c[i]]+1);
        else printf("%lld\n",ans2[i]);
    }
    return 0;
}