51nod 1297 管理二叉树

来源:互联网 发布:纯t是什么意思网络用语 编辑:程序博客网 时间:2024/05/23 11:23

1297 管理二叉树
题目来源: HackerRank
基准时间限制:3 秒 空间限制:131072 KB 分值: 640 难度:8级算法题
 收藏
 关注
一个初始为空的二叉搜索树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示例
847318265
Output示例
0141020355276
李陶冶 (题目提供者)



【分析】

动态点分治

预处理出来各个节点与各层分治中心的距离等信息,按时间顺序逐个插入点统计答案。




【代码】

//51nod 1297 管理二叉树 #include<bits/stdc++.h>#define inf 1e6#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(int i=j;i<=k;i++)using namespace std;const int mxn=150005;set <int> s;bool vis[mxn];ll ans,tmp;int n,m,T,cnt,tot,root;int head[mxn],ch[mxn][2];ll ans1[mxn],ans2[mxn],num[mxn];int a[mxn],dep[mxn],pre[mxn],nxt[mxn];int anc[mxn][22],dis[mxn][22],mx[mxn],sz[mxn];struct edge {int to,next;} f[mxn<<1];inline void add(int u,int v){f[++cnt].to=v,f[cnt].next=head[u],head[u]=cnt;f[++cnt].to=u,f[cnt].next=head[v],head[v]=cnt;}inline void dfs_size(int u,int fa){sz[u]=1,mx[u]=0;for(int i=head[u];i;i=f[i].next){int v=f[i].to;if(v==fa || vis[v]) continue;dfs_size(v,u);sz[u]+=sz[v];mx[u]=max(mx[u],sz[v]);}mx[u]=max(mx[u],tot-sz[u]);if(mx[u]<mx[root]) root=u;}inline void dfs_dis(int u,int fa,int Anc,ll Dis){dep[u]++;anc[u][dep[u]]=Anc;dis[u][dep[u]]=Dis;for(int i=head[u];i;i=f[i].next){int v=f[i].to;if(v==fa || vis[v]) continue;dfs_dis(v,u,Anc,Dis+1);}}inline void dfs(int u){mx[root=0]=inf;dfs_size(u,0);dfs_dis(root,root,root,0);dep[root]--,vis[root]=1;for(int i=head[root];i;i=f[i].next){int v=f[i].to;if(vis[v]) continue;dfs_size(v,0);    tot=sz[v],dfs(v);}}inline void solve(int u){tmp=ans1[u];for(int i=dep[u];i>1;i--){ll Dis=dis[u][i-1];tmp+=ans1[anc[u][i-1]]-ans2[anc[u][i]];tmp+=Dis*(num[anc[u][i-1]]-num[anc[u][i]]);}ans+=tmp,num[u]++;for(int i=dep[u];i>1;i--){ll Dis=dis[u][i-1];ans1[anc[u][i-1]]+=Dis;ans2[anc[u][i]]+=Dis;num[anc[u][i-1]]++;}printf("%lld\n",ans);}inline void build(){set <int>::iterator pr,nt;s.insert(a[1]);fo(i,2,n){s.insert(a[i]);pr=nt=s.lower_bound(a[i]);if(nt!=s.end()){nt++;if(nt!=s.end())  nxt[a[i]]=(*nt);}if(pr!=s.begin())  pr--,pre[a[i]]=(*pr);}fo(i,2,n){int u=a[i];if(!pre[u] || ch[pre[u]][1]){ch[nxt[u]][0]=u;add(nxt[u],u);//printf("connect=[%d,%d]\n",nxt[u],u);continue;}if(!nxt[u] || ch[nxt[u]][0]){ch[pre[u]][1]=u;add(pre[u],u);//printf("connect=[%d,%d]\n",pre[u],u);}}}int main(){scanf("%d",&n);fo(i,1,n)  scanf("%d",&a[i]);build();tot=n,dfs(1);fo(i,1,n) anc[i][++dep[i]]=i;fo(i,1,n) solve(a[i]);return 0;}