51nod1297 管理二叉樹 點分治

2021-07-29 10:17:51 字數 1606 閱讀 3181

乙個初始為空的二叉搜尋樹t,以及1到n的乙個排列p: 。我們向這個二叉搜尋樹t新增這些數,從a1開始, 接下來是 a2, …, 以an結束。在每乙個新增操作後,輸出t上每對節點之間的距離之和。建樹暴力會超時,觀察可知乙個點只會掛在比它小的點中最大的點的右邊或比它大的點中最小的點的左邊,並且有且只有乙個位置是空的,我們可以用set來求這個。

接下來就是建重心樹(點分樹),找乙個重心然後剖開樹,子節點是剖開的樹的重心。接下來求的是乙個點和比它先加入的點的距離和,可以考慮在重心樹上求答案,每個點儲存所有子節點中加入過的點到它的距離和,到它父親的距離和,還有所有子節點中加入過點的數,即可求出答案。

#include

#include#include#include#include#define lf double

#define ll long long

#define min(a,b) ((ab)?a:b)

#define fo(i,j,k) for(int i=j;i<=k;i++)

#define fd(i,j,k) for(int i=j;i>=k;i--)

#define for(i,j) for(int i=begin[j];i;i=next[i])

using namespace std;

intconst mxn=1e5,mxm=2*1e5;

int n,gra,mxb,size[mxn+9],fa[mxn+9],vis[mxn+9],num[mxn+9],dep[mxn+9],son[mxn+9][2],fat[mxn+9][18],begin[mxn+9],to[mxm+9],

next[mxm+9];ll f[mxn+9],g[mxn+9],ans;

struct rec

friend bool operator<(rec x,rec y)

int cmid(int

now,int tsize)

}vis[now]=0;

if(size[now]>=(tsize>>1))return now;

return 0;

}void csize(int

now)

vis[now]=0;

}int build(int

now)

return now;

}int cdis(int u,int v)

void dfs(int

now,int pre)

int main())),next=*(++s.find());

if((!pre.pos)||(son[pre.pos][1]))

son[next.pos][0]=i,insert(next.pos,i),insert(i,next.pos);

else son[pre.pos][1]=i,insert(pre.pos,i),insert(i,pre.pos);

}int root=build(1);

dfs(1,0);mxb=log(n)/log(2);

fo(j,1,mxb)fo(i,1,n)fat[i][j]=fat[fat[i][j-1]][j-1];

ll ans=0;

fo(i,1,n)

return 0;

}

51nod 1297 管理二叉樹

給定乙個n的排列,用它建出二叉搜尋樹。輸出每次插入後所有節點兩兩之間距離和。n 100000 考慮離線做。首先把這棵樹建出來。建樹可以o n 具體點 可以發現,插入乙個值x時,它一定是之前已經插入的數中,和它相鄰的兩個數中後插入的數值兒子。比如 4 7 3 1 8 2 6 5。1是3的左兒子,2是1...

51nod 1297 管理二叉樹

乙個初始為空的二叉搜尋樹t,以及1到n的乙個排列p 我們向這個二叉搜尋樹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...

二叉樹 二叉樹

題目描述 如上所示,由正整數1,2,3 組成了一顆特殊二叉樹。我們已知這個二叉樹的最後乙個結點是n。現在的問題是,結點m所在的子樹中一共包括多少個結點。比如,n 12,m 3那麼上圖中的結點13,14,15以及後面的結點都是不存在的,結點m所在子樹中包括的結點有3,6,7,12,因此結點m的所在子樹...