乙個初始為空的二叉搜尋樹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+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)output第2 - n + 1行:每行1個數,對應排列的元素。(1 <= ai <= n)
輸出共n行,每行1個數,對應新增當前元素後,每對節點之間的距離之和。input示例
847output示例3182
65
0141020
3552
76
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set+動態點分治~
我們用乙個set記錄所有點,加入點時,尋找它最大的小於它的節點和最小的大於它的節點,看它們有沒有右/左子節點,沒有就加上,可以快速建圖。
——這裡和寵物收養所是一樣的。
然後就是動態點分治辣!
#include#include#include#includeusing namespace std;
#define ll long long
const int inf=999999999;
int n,x,y,z,a[100001],f[100001],dep[100001],anc[100001][22],siz[100001];
int fi[100005],w[200010],ne[200010],cnt,tot,root,mx[100001],dis[100001][22];
ll ans1[100001],ans2[100001],ans,num[100001];
bool c[100001][2],vis[100001];
sets;
set::iterator le,ri;
int read()
while(ch>='0' && ch<='9')
return x*f;
}void add(int u,int v)
void findroot(int u,int fa)
mx[u]=max(mx[u],tot-siz[u]);
if(mx[u]1;i--)
num[u]++;
for(int i=dep[u];i>1;i--)
printf("%lld\n",ans);
}int main()
tot=n;dfs(1);
for(int i=1;i<=n;i++) anc[i][++dep[i]]=i;
for(int i=1;i<=n;i++) sol(a[i]);
return 0;
}
51nod 1297 管理二叉樹
給定乙個n的排列,用它建出二叉搜尋樹。輸出每次插入後所有節點兩兩之間距離和。n 100000 考慮離線做。首先把這棵樹建出來。建樹可以o n 具體點 可以發現,插入乙個值x時,它一定是之前已經插入的數中,和它相鄰的兩個數中後插入的數值兒子。比如 4 7 3 1 8 2 6 5。1是3的左兒子,2是1...
51nod1297 管理二叉樹 點分治
乙個初始為空的二叉搜尋樹t,以及1到n的乙個排列p 我們向這個二叉搜尋樹t新增這些數,從a1開始,接下來是 a2,以an結束。在每乙個新增操作後,輸出t上每對節點之間的距離之和。建樹暴力會超時,觀察可知乙個點只會掛在比它小的點中最大的點的右邊或比它大的點中最小的點的左邊,並且有且只有乙個位置是空的,...
二叉樹 二叉樹
題目描述 如上所示,由正整數1,2,3 組成了一顆特殊二叉樹。我們已知這個二叉樹的最後乙個結點是n。現在的問題是,結點m所在的子樹中一共包括多少個結點。比如,n 12,m 3那麼上圖中的結點13,14,15以及後面的結點都是不存在的,結點m所在子樹中包括的結點有3,6,7,12,因此結點m的所在子樹...