[51nod1297]管理二叉树

  一个初始为空的二叉搜索树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个数,对应添加当前元素后,每对节点之间的距离之和。

 

 

  先把树求出来。。具体的话就是每次添加元素之后,找到这个数的前驱后继,哪个有空位这个元素就在哪。随便写个什么数据结构。

  求节点的距离和的话。。我写了点分治,每次查找完往里面加点...查找啊去重啊什么的都是一样的套路...

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cmath>
  7 #include<cstdlib>
  8 #include<bitset>
  9 //#include<ctime>
 10 #define ll long long
 11 #define ull unsigned long long
 12 #define ui unsigned int
 13 #define d double
 14 //#define ld long double
 15 using namespace std;
 16 const int maxn=100233,mxnode=maxn;
 17 struct zs{int too,pre;}e[maxn<<1];int tot,last[maxn];
 18 int lc[mxnode],rc[mxnode],v[mxnode],rnd[mxnode],tt;int V,PRE,AFT,rt;bool u[maxn][2];
 19 int sz[maxn],mx[maxn],RT,POI,dis[maxn],st[maxn],top,mxdep[maxn];bool del[maxn];
 20 int bel[maxn][20],belson[maxn<<1][20],dist[maxn][20],_sz[maxn],_sonsz[maxn<<1];int ID;
 21 ll _sum[maxn],_sonsum[maxn<<1];
 22 int a[maxn];
 23 int i,j,k,n,m;
 24 
 25 int ra,fh;char rx;
 26 inline int read(){
 27     rx=getchar(),ra=0,fh=1;
 28     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
 29     if(rx=='-')fh=-1,rx=getchar();
 30     while(rx>='0'&&rx<='9')ra=ra*10+rx-48,rx=getchar();return ra*fh;
 31 }
 32 inline void maxs(int &a,int b){if(b>a)a=b;}
 33 inline void lturn(int &x){int R=rc[x];rc[x]=lc[R],lc[R]=x,x=R;}
 34 inline void rturn(int &x){int L=lc[x];lc[x]=rc[L],rc[L]=x,x=L;}
 35 inline void insert(int &x){
 36     if(!x){x=++tt,v[x]=V,rnd[x]=rand();return;}
 37     if(V<v[x]){
 38         insert(lc[x]);
 39         if(rnd[lc[x]]<rnd[x])rturn(x);
 40     }else{
 41         insert(rc[x]);
 42         if(rnd[rc[x]]<rnd[x])lturn(x);
 43     }
 44 }
 45 void getpre(int x){
 46     if(!x)return;
 47     if(v[x]<V)PRE=v[x],getpre(rc[x]);else getpre(lc[x]);
 48 }
 49 void getaft(int x){
 50     if(!x)return;
 51     if(v[x]>V)AFT=v[x],getaft(lc[x]);else getaft(rc[x]);
 52 }
 53 inline void ins(int a,int b){
 54     e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;
 55     e[++tot].too=a,e[tot].pre=last[b],last[b]=tot;
 56 }
 57 
 58 
 59 void getrt(int x,int fa){
 60     sz[x]=1,mx[x]=0;
 61     for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa&&!del[e[i].too])
 62         getrt(e[i].too,x),maxs(mx[x],sz[e[i].too]),sz[x]+=sz[e[i].too];
 63     maxs(mx[x],POI-sz[x]);
 64     if(mx[x]<mx[RT])RT=x;
 65 }
 66 void getpoi(int x,int fa){
 67     dis[x]=dis[fa]+1,st[++top]=x,sz[x]=1;
 68     for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa&&!del[e[i].too])
 69         getpoi(e[i].too,x),sz[x]+=sz[e[i].too];
 70 }
 71 void work(int x,int dep){
 72     int i,p;
 73     RT=0,getrt(x,0),x=RT,mxdep[x]=dep,bel[x][dep]=x,dist[x][dep]=dis[x]=0;
 74     for(i=last[x];i;i=e[i].pre)if(!del[e[i].too]){
 75         getpoi(e[i].too,x);ID++;
 76         while(top)p=st[top--],bel[p][dep]=x,belson[p][dep]=ID,dist[p][dep]=dis[p];
 77     }
 78     del[x]=1,sz[x]=-233;
 79     for(i=last[x];i;i=e[i].pre)if(!del[e[i].too])
 80         POI=sz[e[i].too],work(e[i].too,dep+1);
 81 }
 82 
 83 int main(){
 84     n=read();
 85     for(i=1;i<=n;i++){
 86         a[i]=read();
 87         if(i>1){
 88             PRE=AFT=0,V=a[i],getpre(rt),getaft(rt),
 89             insert(rt);
 90             if(!PRE||!AFT)ins(PRE|AFT,a[i]),u[PRE|AFT][PRE>0]=1;
 91             else if(!u[PRE][1])u[PRE][1]=1,ins(PRE,a[i]);
 92             else u[AFT][0]=1,ins(AFT,a[i]);
 93         }else V=a[i],insert(rt);
 94     }
 95 //    for(i=1;i<=n;i++)for(j=last[i];j;j=e[j].pre)printf("%d-->%d\n",i,e[j].too);
 96     
 97     mx[0]=1<<30,POI=n,work(a[1],1);ll ans=0;int fa,son,dis;
 98     for(i=1;i<=n;i++){
 99         k=a[i];
100         
101         ans+=_sum[k],_sz[k]++;
102         for(j=mxdep[k]-1;j;j--)
103             fa=bel[k][j],son=belson[k][j],dis=dist[k][j],
104             ans+=1ll*dis*(_sz[fa]-_sonsz[son])+_sum[fa]-_sonsum[son],
105             _sz[fa]++,_sonsz[son]++,_sum[fa]+=dis,_sonsum[son]+=dis;
106         
107         printf("%lld\n",ans);
108     }
109 }
View Code

 

转载于:https://www.cnblogs.com/czllgzmzl/p/5956304.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值