BZOJ4928 第二題 樹hash 倍增

2022-05-20 17:43:28 字數 1501 閱讀 3052

對於一棵有根樹,定義乙個點u的k-子樹為u的子樹中距離u不超過k的部分。

注意,假如u的子樹中不存在距離u為k的點,則u的k-子樹是不存在的。

定義兩棵子樹是相同的,當且僅當不考慮點的標號時,他們的形態是相同的(兒子的順序也需要考慮)。給定一棵n個點,點的標號在[1,n],以1為根的有根樹。問最大的k,使得存在兩個點u !=v,滿足u的k-子樹與v的k-子樹相同。

第一行輸入乙個正整數n。

接下來讀入n個部分,第i個部分描述點i的兒子,且以順序給出。

每個部分首先讀入乙個整數x,代表兒子個數。

接下來x個整數,代表從左到右兒子的標號

n ≤ 100000,保證給出的樹是合法的

輸出乙個整數k,代表最大的合法的k

8 1 2 2

3 40

1 5

26 7

0 1 8 0

3題解:依舊是集訓原題。

由於答案是可二分的,考慮倍增。我們用f[i][x]表示x的-(1<

然後看標程看到好多種hash的方法,這裡只說一種比較簡單的。

特別地,我們令f[0][x]的hash值為x的兒子數量(你可以想象,如果一棵樹的dfs序確定了,dfs序上每個點的權值就是它的兒子數量,那麼這個dfs序就能唯一的表示一棵樹)。然後在合併-a和-b的時候如何處理呢?我們按照dfs序遍歷x的所有到x的距離為a的子孫,然後設它們的-b子樹的hash值分別為b1,b2...bm,那麼我們相當於得到乙個序列,我們將這個序列hash一下(hash=a*basem+b1*basem-1+...bm*1)。最後,我們將所有點的hash值排個序,反離散化一下,得到的排名就是x的-(a+b)子樹的hash值。

#include #include #include #include #include using namespace std;

typedef unsigned long long ull;

const int maxn=100010;

int n,mx,ans,len,now;

const ull bas=2543323;

ull hs[20][maxn],f[maxn],nf[maxn],pv[maxn];

vector ch[maxn];

int dep[maxn],p[maxn],st[maxn],md[maxn],vis[maxn];

int rd()

while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();

return ret*f;

}void dfs(int x,ull *a,ull *b,ull *c)

}int check(ull *a,ull *b,ull *c,int l)

} return 0;

}int main()

for(i=1;i<=16;i++) merge(hs[i],hs[i-1],hs[i-1],1<=0;i--)

{ if(check(nf,f,hs[i],ans+(1<

網易互娛 9 7 第二批 筆試 第二題 層次樹

輸入 28 2 1 1 1 5 3 4 1 6 2 1 1 3 0 2 2 4 7 7 1 1 2 1 1 821 6 1 52 4 1 80 0 3 31 7 1 21 1 1 59 1 1 50 5 1 48 1 1 輸出 yes no網易互娛 第二批筆試第二題 層次樹 調了我乙個小時,被自己蠢...

2023年第二考研題 二叉鍊錶轉換為二叉樹

編寫程式將儲存在雙向鍊錶中的數儲存到二叉排序樹中,要求轉換過程中數儲存的結點位址不變。8分 定義乙個通用結構體 定義乙個通用結構體 typedef int elemtype typedef struct dulnode dulnode,bitnode 向二叉樹中新增結點 void addnode b...

2014微軟程式設計之美初賽第一場第二題 樹

時間限制 4000ms 單點時限 2000ms 記憶體限制 256mb 有乙個n個節點的樹,其中點1是根。初始點權值都是0。乙個節點的深度定義為其父節點的深度 1,特別的,根節點的深度定義為1。現在需要支援一系列以下操作 給節點u的子樹中,深度在l和r之間的節點的權值 這裡的深度依然從整個樹的根節點...