HDU 5788 Level Up

Description

The Arithmetic Coconut Median company has n employees. Every person has a direct supervisor except the boss. Boss’s number is 1. Everyone has a Ability Value Ai . The wage of person i is the Median of Ability Value of person i and his (direct and indirect) subordinates. The ACM company decided to send a person to study in the center of the universe, then the Ability Value of this person will become 100000.
Please calculate the maximum sum of wages of all people.
Define the Median of t integers: the t2 th smallest number of these t integers.

Solution

这题数据似乎十分的水,完全错的就可以直接过掉所有数据了

首先我们对于每个节点,如果它的子树中比原中位数小的点点权被修改,则其中位数位置向后滑动1

也就是说我们可以一开始predfs出每个点的mid+1和mid的差值,在dfs到某节点的时候观察差值被修改的最大值。

查询中位数可以用主席树,dfs过程找最大差值可以用权值BIT

Code

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<time.h>
#include<stdlib.h>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
typedef double db;
typedef unsigned ud;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;

#define fi first 
#define se second
#define pb push_back
#define ph push

const int INF=(ud)-1>>1;
const ll inf=(ull)-1>>1;

template<class T>void rd(T &a){
    a=0;char c;
    while(c=getchar(),!isdigit(c));
    do a=a*10+(c^48);
        while(c=getchar(),isdigit(c));
}
template<class T>void nt(T x){
    if(!x)return;
    nt(x/10);
    putchar(48+x%10);
}
template<class T>void pt(T x){
    if(!x)putchar('0');
    else nt(x);
}
template<class T>void Max(T &a,T b){
    if(a<b)a=b;
}
template<class T>void Min(T &a,T b){
    if(a==-1||a>b)a=b;
}
const int M=1e5+5;
const int N=2e6+5;
const int P=1e5;
int n,Lim;
struct Chairman_Tree{
    int ls[N],rs[N],cnt[N],allc;
    inline void clear(){
        for(int i=1;i<=allc;++i)
            ls[i]=rs[i]=cnt[i]=0;
        allc=0;
    }
    inline void update(int &rt,int ot,int s,int l=1,int r=Lim){
        rt=++allc;
        ls[rt]=ls[ot],rs[rt]=rs[ot],cnt[rt]=cnt[ot]+1;
        if(l==r)return;
        int mid=l+r>>1;
        if(s<=mid)update(ls[rt],ls[ot],s,l,mid);
        else update(rs[rt],rs[ot],s,mid+1,r);
    }
    inline int query(int rt,int ot,int s,int l=1,int r=Lim){//询问第s小
        if(l==r)return l;
        int mid=l+r>>1;
        int w=cnt[ls[rt]]-cnt[ls[ot]];
        if(s<=w)return query(ls[rt],ls[ot],s,l,mid);
        else return query(rs[rt],rs[ot],s-w,mid+1,r);
    }
}ct;
struct BIT{
    int bit[M];
    inline void add(int x,int a){
        for(;x<=Lim;x+=x&-x)bit[x]+=a;
    }
    inline ll sum(int x){
        ll res=0;
        for(;x;x-=x&-x)res+=bit[x];
        return res;
    }
    inline void clear(){
        memset(bit,0,sizeof(bit));
    }
}T;
int A[M],f[M];
struct Edge{
    int to,nxt;
}G[M<<1];
int head[M],tot_edge;
inline void add_edge(int from,int to){
    G[tot_edge]=(Edge){to,head[from]};
    head[from]=tot_edge++;
}
int rt[M],dfn[M],dfs_clock,val[M],mid[M],sz[M];
ll sum,Mx;
inline void predfs(int v){
    dfn[v]=++dfs_clock;
    ct.update(rt[dfs_clock],rt[dfs_clock-1],A[v]);
    sz[v]=1;
    for(int i=head[v];~i;i=G[i].nxt){
        int to=G[i].to;
        predfs(to);
        sz[v]+=sz[to];
    }
    int s=sz[v]+1>>1;
    int w1=0,w2=0;
    w1=ct.query(rt[dfs_clock],rt[dfn[v]-1],s);
    if(~head[v])w2=ct.query(rt[dfs_clock],rt[dfn[v]-1],s+1);
    mid[v]=w1,val[v]=max(0,w2-w1);
    sum+=w1;
}
inline void dfs(int v){
    T.add(mid[v],val[v]);
    ll w=T.sum(Lim)-T.sum(A[v]-1);
    if(head[v]==-1)w+=P-A[v];
    Max(Mx,w);
    for(int i=head[v];~i;i=G[i].nxt)
        dfs(G[i].to);
    T.add(mid[v],-val[v]);
}
inline void gao(){
    memset(head,-1,sizeof(head));
    sum=Mx=tot_edge=dfs_clock=Lim=0;
    ct.clear(),T.clear();
    memset(rt,0,sizeof(rt));
    for(int i=1;i<=n;++i)rd(A[i]),Max(Lim,A[i]);
    for(int i=2;i<=n;++i)
        rd(f[i]),add_edge(f[i],i);
    predfs(1);
    dfs(1);
    cout<<sum+Mx<<endl;
}
//#define LOCAL
int main(){
#ifdef LOCAL
    freopen("1008.in","r",stdin);
    freopen("ans.out","w",stdout);
    int size = 256 << 20; // 256MB
    char *p = (char*)malloc(size) + size;
    __asm__("movl %0, %%esp\n" :: "r"(p));
#endif
    for(;cin>>n;)gao();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值