51nod1297 管理二叉树

 

题目来源: HackerRank
基准时间限制:3 秒 空间限制:131072 KB 分值: 640
一个初始为空的二叉搜索树T,以及1到N的一个排列P: {a1, a2, ..., aN}。我们向这个二叉搜索树T添加这些数,从a1开始, 接下来是 a2, ..., 以aN结束。在每一个添加操作后,输出T上每对节点之间的距离之和。
例如:4 7 3 1 8 2 6 5。最终的二叉树为:
 
       4
     /   \
    3      7   
  /      /   \
 1      6     8
  \    /
   2  5
 
节点两两之间的距离和 = 6+5+5+4+3+2+1+5+4+4+3+2+1+4+3+3+2+1+3+2+2+1+2+1+1+2+1+3 = 76
Input
第1行:1个数N。(1 <= N <= 100000)
第2 - N + 1行:每行1个数,对应排列的元素。(1 <= ai <= N)
Output
输出共N行,每行1个数,对应添加当前元素后,每对节点之间的距离之和。
Input示例
8
4
7
3
1
8
2
6
5
Output示例
0
1
4
10
20
35
52
76

 

树 规律题 动态点分治

直接模拟建树妥妥被卡。

分析一波可以发现,将一个点x添加进树的时候,在所有已有点中找到x的前驱和后继,x要么是前驱的右儿子,要么是前驱的左儿子。

思考一下或者手玩一波会发现“前驱的右儿子”和“后继的左儿子“不会同时为空,所以要添加到哪里是确定的。

我们可以离线操作,先将树建好,之后按顺序每次添加一个点,统计它到所有已有点的距离。

剩下的部分显然是动态点分治模板题。

 

写完WA了一半点,旁边czy说:“想必没有开LL”

开了LL以后还有三个点WA,旁边czy说:“想必数组不够大”

开大了数组就AC辣

他真是个小天才!

 

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cmath>
  6 #include<set>
  7 #define LL long long
  8 using namespace std;
  9 const int INF=0x3f3f3f3f;
 10 const int mxn=150010;
 11 int read(){
 12     int x=0,f=1;char ch=getchar();
 13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 15     return x*f;
 16 }
 17 struct edge{
 18     int v,nxt;
 19 }e[mxn<<1];
 20 int hd[mxn],mct=0;
 21 void add_edge(int u,int v){
 22     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
 23 }
 24 void insert(int u,int v){
 25     add_edge(u,v);add_edge(v,u);return;
 26 }
 27 int sz[mxn],mc[mxn],rot,smm;
 28 int dep[mxn],dis[mxn][23];
 29 int an[mxn][23];
 30 LL ans1[mxn],ans2[mxn],num[mxn];
 31 LL nowans;
 32 bool vis[mxn];
 33 void DFS_sz(int u,int fa){
 34     sz[u]=mc[u]=1;
 35     for(int i=hd[u];i;i=e[i].nxt){
 36         int v=e[i].v;;if(v==fa || vis[v])continue;
 37         DFS_sz(v,u);
 38         sz[u]+=sz[v];
 39         mc[u]=(sz[v]>mc[u])?sz[v]:mc[u];
 40     }
 41     mc[u]=max(mc[u],smm-sz[u]);
 42     if(mc[u]<mc[rot])rot=u;
 43     return;
 44 }
 45 void calc(int u,int fa,int ance,int dist){
 46     an[u][++dep[u]]=ance;
 47     dis[u][dep[u]]=dist;
 48     for(int i=hd[u];i;i=e[i].nxt){
 49         int v=e[i].v;
 50         if(v==fa || vis[v])continue;
 51         calc(v,u,ance,dist+1);
 52     }
 53     return;
 54 }
 55 void solve(int x){
 56     vis[x]=1;
 57 //    printf("solve:%d\n",x);
 58     calc(x,x,x,0);dep[x]--;
 59     for(int i=hd[x];i;i=e[i].nxt){
 60         int v=e[i].v;
 61         if(!vis[v]){
 62             smm=sz[v]; mc[rot=0]=INF;
 63             DFS_sz(v,x);
 64             solve(rot);
 65         }
 66     }
 67     return;
 68 }
 69 void add(int u){
 70     LL tmp=ans1[u];
 71     for(int i=dep[u];i>1;i--){
 72         LL dist=dis[u][i-1];
 73         tmp+=ans1[an[u][i-1]]-ans2[an[u][i]];
 74         tmp+=dist*(num[an[u][i-1]]-num[an[u][i]]);
 75     }
 76     nowans+=tmp;
 77     num[u]+=1;
 78     for(int i=dep[u];i>1;i--){
 79         LL dist=dis[u][i-1];
 80         ans1[an[u][i-1]]+=dist*1;
 81         ans2[an[u][i]]+=dist*1;
 82         num[an[u][i-1]]+=1;
 83     }
 84     return;
 85 }
 86 //
 87 int ch[mxn][2];
 88 //int st[mxn],top=0;
 89 int n,x[mxn],M[mxn],U[mxn];
 90 set<int>st;
 91 void init(){
 92     st.insert(x[1]);set<int>::iterator it,it2;
 93     for(int i=2;i<=n;i++){
 94         st.insert(x[i]);
 95         it=it2=st.lower_bound(x[i]);
 96         if(it!=st.end()){it++;if(it!=st.end())U[i]=(*it);}
 97         if(it2!=st.begin()){it2--; M[i]=(*it2);}
 98     }
 99     for(int i=2;i<=n;i++){
100         if(!M[i] || ch[M[i]][1]){
101             ch[U[i]][0]=x[i];
102             insert(U[i],x[i]);
103             continue;
104         }
105         if(!U[i] || ch[U[i]][0]){
106             ch[M[i]][1]=x[i];
107             insert(M[i],x[i]);
108         }
109     }
110     return;
111 }
112 int main(){
113     int i,j;
114     n=read();
115     for(i=1;i<=n;i++)x[i]=read();
116     init();
117     smm=n;
118     mc[rot=0]=INF;
119     DFS_sz(1,0);
120     solve(rot);
121     for(i=1;i<=n;i++){
122         an[i][++dep[i]]=i;
123         dis[i][dep[i]]=0;
124     }
125     for(i=1;i<=n;i++){
126         add(x[i]);
127         printf("%lld\n",nowans);
128     }
129     return 0;
130 }

 

posted @ 2017-06-29 17:19  SilverNebula  阅读(312)  评论(0编辑  收藏  举报
AmazingCounters.com