zoukankan      html  css  js  c++  java
  • hdu_5788_Level Up(树状数组+主席树)

    题目链接:hdu_5788_Level Up

    题意:

    有一棵树,n个节点,每个节点有个能力值A[i],mid[i],mid的值为第i节点的子树的中位数(包括本身),现在让你将其中的一个节点的A值改为1e5,问所有的mid的和最大问多少。

    题解:

    我们可以知道,如果改变其中一个的A[i],如果A[i]是比他父亲节点的mid小,那么他父亲的此时的中位数就会向后移一位

    比如 1 2 3 4 5,第3个点是第2个点的父亲,如果改变了第二个点的A值,那么此时变成了1 3 4 5 1e5,第二个点的父亲的mid就变成了4,相比之前向后移了一位。

    所以我们可以用主席树来支持查询中位数,然后预处理出每个节点的mid的值和mid+1的值。

    最后用树状数组+dfs维护一个最大的差值。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;i++)
     3 using namespace std;
     4 typedef long long ll;
     5 
     6 const int N=1e5+7,P=1e5;
     7 int A[N],n,g[N],v[N],nxt[N],ed,x,tot,root[N],dfn[N],dfs_idx,sz[N],mid[N],val[N];
     8 ll sum[N],ans,mx;
     9 
    10 inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
    11 void init(){ed=tot=dfs_idx=0,ans=mx=0;memset(sum,0,sizeof(sum));memset(g,0,sizeof(g));}
    12 inline void upmax(ll &a,ll b){if(a<b)a=b;}
    13 //------------------树状数组
    14 inline void add(int x,int c){while(x<=P)sum[x]+=c,x+=x&-x;}
    15 inline ll ask(int x){ll an=0;while(x)an+=sum[x],x-=x&-x;return an;}
    16 //------------------主席树
    17 struct node{int l,r,sum;}T[N*30];
    18 
    19 inline void update(int &x,int y,int pos,int l=1,int r=P)
    20 {
    21     T[++tot]=T[y],T[tot].sum++,x=tot;
    22     if(l==r)return;
    23     int m=l+r>>1;
    24     if(pos<=m)update(T[x].l,T[y].l,pos,l,m);
    25     else update(T[x].r,T[y].r,pos,m+1,r);
    26 }
    27 
    28 inline int query(int x,int y,int k,int l=1,int r=P)
    29 {
    30     if(l==r)return l;
    31     int m=l+r>>1,sum=T[T[x].l].sum-T[T[y].l].sum;
    32     if(k<=sum)return query(T[x].l,T[y].l,k,l,m);
    33     else return query(T[x].r,T[y].r,k-sum,m+1,r);
    34 }
    35 
    36 void predfs(int u=1)
    37 {
    38     sz[u]=1,dfn[u]=++dfs_idx;
    39     update(root[dfn[u]],root[dfn[u]-1],A[u]);
    40     for(int i=g[u];i;i=nxt[i])predfs(v[i]),sz[u]+=sz[v[i]];
    41     if(!g[u])mid[u]=A[u],val[u]=P-A[u],ans+=A[u];
    42     else
    43     {
    44         int s=sz[u]+1>>1;
    45         mid[u]=query(root[dfs_idx],root[dfn[u]-1],s);
    46         val[u]=query(root[dfs_idx],root[dfn[u]-1],s+1)-mid[u];
    47         ans+=mid[u];
    48     }
    49 }
    50 
    51 void dfs(int u=1)
    52 {
    53     add(mid[u],val[u]);
    54     upmax(mx,ask(P)-ask(A[u]-1));
    55     for(int i=g[u];i;i=nxt[i])dfs(v[i]);
    56     add(mid[u],-val[u]);
    57 }
    58 
    59 int main()
    60 {
    61     while(~scanf("%d",&n))
    62     {
    63         init();
    64         F(i,1,n)scanf("%d",A+i);
    65         F(i,2,n)scanf("%d",&x),adg(x,i);
    66         predfs(),dfs();
    67         printf("%lld
    ",ans+mx);
    68     }
    69     return 0;
    70 }
    View Code
  • 相关阅读:
    Cmake编译SDL2
    glog的使用
    win32下编译glog
    快速阅读《QT5.9 c++开发指南》1
    applyColorMap()研究(如果我对现有的colormap不满意,那么如何具体来做)
    如何判断轮廓是否为圆
    libopencv_shape.so.3.0: cannot open shared object file: No such file or directory 解决笔记
    OpenCV和RTSP的综合研究
    识别复杂的答题卡1(主要算法)
    识别简单的答题卡(Bubble sheet multiple choice scanner and test grader using OMR, Python and OpenCV——jsxyhelu重新整编)
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5933106.html
Copyright © 2011-2022 走看看