BZOJ 4756 Promotion Counting

Posted on 2017-02-01 20:48  ziliuziliu  阅读(350)  评论(0编辑  收藏  举报

用线段树合并水了这题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100500
#define maxe 200500
using namespace std;
int n,x,p[maxn],g[maxn],hash[maxn],nume=1,len=0,tot=0,ans[maxn];
int ls[maxn*20],rs[maxn*20],sum[maxn*20],root[maxn];
struct edge
{
    int v,nxt;
}e[maxe];
int read()
{
    char ch;int f=1,data=0;
    while (ch<'0' || ch>'9')
    {
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0' && ch<='9')
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data*f;
}
void addedge(int u,int v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void pushup(int now) {sum[now]=sum[ls[now]]+sum[rs[now]];}
void build(int &now,int left,int right,int pos)
{
    now=++tot;
    if (left==right) {sum[now]=1;return;}
    int mid=(left+right)>>1;
    if (pos<=mid) build(ls[now],left,mid,pos);
    else build(rs[now],mid+1,right,pos);
    pushup(now);
}
int ask(int now,int left,int right,int l,int r)
{
    if (!now) return 0;
    if ((left==l) && (right==r)) return sum[now];
    int mid=(left+right)>>1;
    if (r<=mid) return ask(ls[now],left,mid,l,r);
    else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r);
    else return ask(ls[now],left,mid,l,mid)+ask(rs[now],mid+1,right,mid+1,r);
}
int merge(int x,int y)
{
    if (!x) return y;
    if (!y) return x;
    ls[x]=merge(ls[x],ls[y]);rs[x]=merge(rs[x],rs[y]);
    pushup(x);
    return x;
}
void dfs(int now,int fath)
{
    int ret=0;
    for (int i=g[now];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (v==fath) continue;
        dfs(v,now);
        ret+=ask(root[v],1,n,p[now]+1,n);
        root[now]=merge(root[now],root[v]);
    }
    ans[now]=ret;
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
        p[i]=read();
        hash[++len]=p[i];
    }
    sort(hash+1,hash+len+1);len=unique(hash+1,hash+len+1)-hash-1;
    for (int i=1;i<=n;i++) p[i]=lower_bound(hash+1,hash+len+1,p[i])-hash;
    for (int i=2;i<=n;i++) 
    {
        x=read();
        addedge(i,x);addedge(x,i);
    }    
    for (int i=1;i<=n;i++) build(root[i],1,n,p[i]);
    dfs(1,1);
    for (int i=1;i<=n;i++) printf("%d\n",ans[i]);
    return 0;
}