青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

(從NOI以后一直在各網站上做水題……誰叫我這么弱做不動難題呢……)
(最近實在感覺到弱得令人吃驚……這樣下去還混什么集訓隊啊……于是只好去挑難題了……中間對某些知識點有一些見解……就總結在這里了囧……)

(最近見到了比較多的樹分治的題目,因此第0個總結的就是樹分治了……)

相關論文

樹分治用于解決有關路徑的問題。
樹分治分為點分治和邊分治(其實還有一種叫“鏈分治”,是樹的路徑剖分思想的更高級的體現,一般鏈分治的題目都可以用路徑剖分解決)。點分治就是每次找到重心,然后把重心去掉,對分成的每兩棵樹之間分別統計路徑信息(以重心的每個相鄰點為根,遍歷整棵子樹即可得到這個根到每個結點的統計信息),就可以知道包含這個重心的所有路徑的信息,然后對于剩下的路徑就是在子樹里面進行同樣的操作了,直到只剩一個點為止(注意這一個點所構成的路徑有時也要處理一下)。邊分治就是每次找到一條邊,使得刪掉這條邊后分成的兩棵子樹大小盡可能平均,然后以刪掉的邊的兩端點為根,分別統計根到兩棵樹中的每個結點的路徑信息,最后合并算路徑,即可得到包含這條邊的所有路徑的信息,剩下的路徑在兩棵樹中遞歸處理。

點分治和邊分治是可以通用的,不管樹上的信息記錄在結點上還是邊上。這時一個很囧的問題就出現了:這兩種分治到底哪個好?這也是本總結討論的重點。
有關“哪個好”的問題顯然要從三種復雜度上考慮。由于點分治和邊分治的空間復雜度均為O(N),因此討論空間復雜度木有意義。所以需要比較的就是時間復雜度和編程復雜度了。
先說時間復雜度。點分治每次找到重心后,需要將重心刪掉然后分成很多棵子樹,對每兩棵子樹之間都要統計一下。如果操作是可反的(比如計數問題:統計某種路徑的條數),可以通過先將所有子樹合在一起統計,再減去兩端點處在相同子樹內的路徑,但是,如果操作不可反(比如找“最優路徑”),就不能這樣做了,只能枚舉所有的子樹對。顯然,如果有S棵子樹,則有O(S2)個子樹對,最壞情況下(星形的樹),S=N-1,此時一一枚舉子樹對必然會導致總時間復雜度升到O(N2)以上。當然這是有解決辦法的,可以從小到大枚舉子樹,每處理完一棵子樹就將其和前面的合并,此時算法效率取決于合并的方法。如果使用歸并法(大小為A的和大小為B的合并次數為A+B),對于星形樹的合并總次數仍然為O(N2),如果能保證大小為A的和大小為B的合并次數為min{A, B},則可以保證合并總次數在O(N)以內,從而可以保證總時間復雜度為O(NlogN)。邊分治由于分成的永遠是兩棵子樹,所以在處理子樹之間的關系上能夠保證O(N),問題是它并不能保證每次分成的兩棵子樹大小非常平均,在最壞情況下(星形的樹),不管刪哪條邊分成的兩棵子樹大小都是一個1一個(N-1),這樣就會使總的時間復雜度上升為O(N2)。

從以上的討論中可以看出,點分治和邊分治最怕的都是星形的樹,也就是那種某個點的度數特別大的樹。相關論文中提到一種辦法通過加無用點的方式將其轉化為二叉樹,從而解決這個問題。這樣一來,點分治和邊分治的時間復雜度都可以保證了。接下來是編程復雜度的問題:點分治需要找重心(三次DFS或BFS),刪掉重心(需要刪點),且分成最多三棵樹,需要處理三對關系,代碼量肯定大一些,而邊分治只需要算出子樹大小后就可以找到最優邊,并且分成的是兩棵樹,更重要的是,在有根樹上刪掉一條邊后,分成的兩棵樹中有一棵已是有根樹,另一棵可以通過扭根的方式將其轉化為有根樹,由于二叉樹扭根是很方便的,所以就不需要每次重新建樹,代碼量較小。綜合以上因素,邊分治更好些。

另外,其實那種加無用點轉化為二叉樹的方式是有問題的,因為它改變了路徑的意義,可能導致一條路徑由于LCA是無用點而在統計時出現錯誤(明明是跨越了重心或最優邊的路徑被當成木有跨越的),但是……這個問題有一種很簡單的解決辦法,想知道是什么……AC了ALOEXT再告訴你……

相關題目:
<1> (2013年候選隊互測•a142857a) 樹
邊分治,每次找到所有點到根路徑的XOR和,以及特殊點的個數,按照特殊點個數排序后有序插入Trie,查找即可。
代碼:
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
#include 
<algorithm>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 200010, MAXS = 31, INF = ~0U >> 2;
struct edge {
    
int a, b, pre, next;
} E[MAXN 
<< 1];
struct sss {
    
int v1, v2;
    
bool operator< (sss s0) const {return v1 < s0.v1;}
} S1[MAXN], S2[MAXN];
int T[MAXN * MAXS][2];
int n, m0, K, sum0, __No, N, A[MAXN], Q[MAXN], ls[MAXN], L[MAXN], R[MAXN], pr[MAXN], SZ[MAXN], V1[MAXN], V2[MAXN], res = -1;
bool B[MAXN], vst[MAXN];
void init_d()
{
    re(i, n) E[i].pre 
= E[i].next = i; if (n & 1) m0 = n + 1else m0 = n;
}
void add_edge(int a, int b)
{
    E[m0].a 
= a; E[m0].b = b; E[m0].pre = E[a].pre; E[m0].next = a; E[a].pre = m0; E[E[m0].pre].next = m0++;
    E[m0].a 
= b; E[m0].b = a; E[m0].pre = E[b].pre; E[m0].next = b; E[b].pre = m0; E[E[m0].pre].next = m0++;
}
void init()
{
    scanf(
"%d%d"&n, &K); init_d();
    
int x, y;
    re(i, n) {scanf(
"%d"&x); B[i] = x;}
    re(i, n) scanf(
"%d"&A[i]);
    re2(i, 
1, n) {scanf("%d%d"&x, &y); add_edge(--x, --y);}
}
int dfs0(int l, int r)
{
    
if (l > r) return -1else if (l == r) return ls[l]; else {
        
int n0; if (!&& r == sum0 - 1) n0 = __No; else n0 = n++;
        
int mid = l + r >> 1, lch = dfs0(l, mid), rch = dfs0(mid + 1, r);
        L[n0] 
= lch; R[n0] = rch; pr[lch] = pr[rch] = n0; return n0;
    }
}
void prepare()
{
    
int x, y; Q[0= 0; vst[0= 1; pr[0= -1;
    
for (int front=0, rear=0; front<=rear; front++) {
        x 
= Q[front]; sum0 = 0;
        
for (int p=E[x].next; p != x; p=E[p].next) {
            y 
= E[p].b;
            
if (!vst[y]) {ls[sum0++= y; vst[y] = 1; Q[++rear] = y;}
        }
        
if (sum0 > 1) {__No = x; dfs0(0, sum0 - 1);} else if (sum0 == 1) {L[x] = ls[0]; pr[ls[0]] = x; R[x] = -1;} else L[x] = R[x] = -1;
    }
}
void solve(int No, int n0)
{
    
if (n0 == 1) {
        
if (B[No] >= K && A[No] > res) res = A[No];
        
return;
    }
    
int x, _x, y, minv = INF, _n0 = n0 >> 1; Q[0= No;
    
for (int front=0, rear=0; front<=rear; front++) {
        x 
= Q[front];
        
if ((y = L[x]) >= 0) Q[++rear] = L[x];
        
if ((y = R[x]) >= 0) Q[++rear] = R[x];
    }
    rre(i, n0) {
        x 
= Q[i]; SZ[x] = 1;
        
if (L[x] >= 0) SZ[x] += SZ[L[x]];
        
if (R[x] >= 0) SZ[x] += SZ[R[x]];
        
if (SZ[x] <= _n0 && _n0 - SZ[x] < minv || SZ[x] > _n0 && SZ[x] - _n0 < minv) {minv = SZ[x] <= _n0 ? _n0 - SZ[x] : SZ[x] - _n0; _x = x;}
    }
    x 
= pr[_x]; pr[_x] = -1if (L[x] == _x) L[x] = -1else R[x] = -1;
    
int sum0 = 1; ls[0= x; while ((y = pr[x]) != -1) {if (L[y] == x) L[y] = -1else R[y] = -1if (L[x] == -1) L[x] = y; else R[x] = y; x = ls[sum0++= y;}
    pr[ls[
0]] = -1; re2(i, 1, sum0) pr[ls[i]] = ls[i - 1];
    
int len1 = 0, len2 = 0;
    Q[
0= _x; V1[_x] = B[_x]; V2[_x] = A[_x]; S1[len1].v1 = V1[_x]; S1[len1++].v2 = V2[_x];
    
for (int front=0, rear=0; front<=rear; front++) {
        x 
= Q[front];
        
if ((y = L[x]) >= 0) {Q[++rear] = y; V1[y] = V1[x] + B[y]; V2[y] = V2[x] ^ A[y]; S1[len1].v1 = V1[y]; S1[len1++].v2 = V2[y];}
        
if ((y = R[x]) >= 0) {Q[++rear] = y; V1[y] = V1[x] + B[y]; V2[y] = V2[x] ^ A[y]; S1[len1].v1 = V1[y]; S1[len1++].v2 = V2[y];}
    }
    Q[
0= ls[0]; V1[ls[0]] = B[ls[0]]; V2[ls[0]] = A[ls[0]]; S2[len2].v1 = V1[ls[0]]; S2[len2++].v2 = V2[ls[0]];
    
for (int front=0, rear=0; front<=rear; front++) {
        x 
= Q[front];
        
if ((y = L[x]) >= 0) {Q[++rear] = y; V1[y] = V1[x] + B[y]; V2[y] = V2[x] ^ A[y]; S2[len2].v1 = V1[y]; S2[len2++].v2 = V2[y];}
        
if ((y = R[x]) >= 0) {Q[++rear] = y; V1[y] = V1[x] + B[y]; V2[y] = V2[x] ^ A[y]; S2[len2].v1 = V1[y]; S2[len2++].v2 = V2[y];}
    }
    sort(S1, S1 
+ len1); sort(S2, S2 + len2); int _len2 = len2 - 1;
    N 
= 1; T[1][0= T[1][1= 0int v0, _v;
    re(i, len1) {
        
while (_len2 >= 0 && S1[i].v1 + S2[_len2].v1 >= K) {
            v0 
= S2[_len2--].v2; x = 1;
            rre(j, MAXS) {
                y 
= (v0 & (1 << j)) > 0;
                
if (!T[x][y]) {T[x][y] = ++N; T[N][0= T[N][1= 0;}
                x 
= T[x][y];
            }
        }
        
if (T[1][0|| T[1][1]) {
            v0 
= S1[i].v2; x = 1; _v = 0;
            rre(j, MAXS) {
                y 
= (v0 & (1 << j)) > 0; _v <<= 1;
                
if (T[x][!y]) {x = T[x][!y]; _v++;} else x = T[x][y];
            }
            
if (_v > res) res = _v;
        }
    }
    x 
= _x; y = ls[0];
    solve(x, len1); solve(y, len2);
}
void pri()
{
    printf(
"%d\n", res);
}
int main()
{
    init();
    prepare();
    solve(
0, n);
    pri();
    
return 0;
}

<2> (VK Cup 2012 R1-D) Distance in Tree
邊分治,很容易實現,不說了。
代碼:不顯示。

Feedback

# re: 關于樹分治的問題  回復  更多評論   

2013-09-01 11:29 by taorunz
重心貌似不是直徑的中點,而是使最大子樹最小的點

# re: 關于樹分治的問題  回復  更多評論   

2014-08-27 08:00 by Ace.Src.
4 1
1 0 0 0
0 4 2 1
1 2
1 3
1 4

那個, 樹那題這個數據應該輸出6吧, 經過2 - 1 - 3得到的是6, 您的程序輸出5.. 到底那個LCA為無用點的方法是什么???

# re: 關于樹分治的問題  回復  更多評論   

2014-12-29 20:25 by Tim_LinYd
請神犇看一下似乎這組數據答案應是 9 但程序給了11?

10 4
0 1 1 0 0 1 0 0 0 1
2 7 8 2 4 7 8 4 7 9
5 10
10 6
6 1
3 7
4 5
7 1
1 9
8 4
8 2
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            美腿丝袜亚洲色图| 免费日韩成人| 欧美jjzz| 亚洲激情在线观看视频免费| 浪潮色综合久久天堂| 篠田优中文在线播放第一区| 亚洲视屏在线播放| 久久av一区二区三区亚洲| 亚洲第一页在线| 永久免费视频成人| 国产一区二区三区四区hd| 国产日韩欧美三级| 韩国成人福利片在线播放| 伊人夜夜躁av伊人久久| 亚洲激情视频| 亚洲欧美激情视频| 久久久亚洲欧洲日产国码αv| 久久久久9999亚洲精品| 美国成人直播| 中国女人久久久| 久久久久久网址| 国产精品久久久久久五月尺| 精品成人一区二区| 亚洲专区免费| 亚洲精品免费电影| 欧美专区日韩专区| 欧美日韩精品欧美日韩精品一| 激情成人综合网| 国产精品久在线观看| 久久精品亚洲精品| 欧美激情麻豆| 久久免费精品视频| 亚洲久久成人| 你懂的视频欧美| 国产精品伦理| 日韩天堂在线观看| 母乳一区在线观看| 羞羞视频在线观看欧美| 欧美精品一区二区在线播放| 亚洲国内高清视频| 亚洲精品综合在线| 欧美日韩国产色站一区二区三区| 亚洲黄色大片| 亚洲欧洲精品一区二区三区波多野1战4 | 亚洲国产cao| 久久亚洲欧美国产精品乐播| 亚洲专区在线| 在线观看国产欧美| 亚洲国产欧美一区二区三区同亚洲 | 一本色道久久综合亚洲精品小说| 你懂的视频一区二区| 99视频精品在线| 亚洲素人一区二区| 激情国产一区| 日韩视频一区二区| 国产欧美亚洲视频| 亚洲大片精品永久免费| 欧美日韩成人一区二区三区| 欧美一级久久久久久久大片| 久久精品视频免费播放| 亚洲人成网站精品片在线观看| 亚洲日本理论电影| 欧美一区二区精品| 一区二区三区精密机械公司| 亚洲欧美区自拍先锋| 亚洲精品在线观看免费| 亚洲天堂久久| 亚洲色图综合久久| 牛牛国产精品| 久久久精品网| 国产婷婷精品| 亚洲制服丝袜在线| 亚洲视频欧美视频| 男女精品视频| 免费亚洲网站| 在线观看不卡| 女仆av观看一区| 欧美大片在线观看一区二区| 黑人一区二区三区四区五区| 亚洲男人的天堂在线aⅴ视频| 99国产精品久久久| 欧美三区在线| 欧美黄色视屏| 亚洲欧洲日本在线| 欧美三级视频在线观看| 亚洲影音先锋| 久久另类ts人妖一区二区| 欧美裸体一区二区三区| 亚洲精品一区在线观看香蕉| 亚洲欧美激情一区| 经典三级久久| 欧美视频在线播放| 亚洲欧美精品suv| 欧美xart系列在线观看| 亚洲一区二区免费视频| 国产亚洲一级| 欧美人与性动交α欧美精品济南到| 日韩一级欧洲| 久久偷看各类wc女厕嘘嘘偷窃| 亚洲人成在线观看| 亚洲一区二区精品视频| 可以免费看不卡的av网站| 欧美日韩一区国产| 国产精品专区一| 另类春色校园亚洲| 国产在线拍偷自揄拍精品| 久久精品国产精品 | 极品av少妇一区二区| 亚洲国产婷婷香蕉久久久久久| 国产一区二区三区直播精品电影 | 欧美高潮视频| 午夜在线视频一区二区区别 | 日韩一级成人av| 国产一区在线视频| 国产精品久久久久久久久果冻传媒| 久久精品国产亚洲a| 午夜精品久久久久久久99热浪潮| 亚洲人成亚洲人成在线观看图片| 久久久久女教师免费一区| 欧美一区二区在线免费观看| 亚洲综合成人婷婷小说| 亚洲——在线| 久久精品系列| 欧美+日本+国产+在线a∨观看| 蜜桃av一区| 99精品国产在热久久婷婷| 99精品视频网| 久久国产婷婷国产香蕉| 亚洲欧洲av一区二区| 国产精品免费一区二区三区观看| 中文在线不卡| 午夜精品成人在线| 久久本道综合色狠狠五月| 久久黄色网页| 欧美国产精品劲爆| 亚洲精品久久久久中文字幕欢迎你| 欧美国产视频一区二区| 久久精品国产999大香线蕉| 免费不卡在线视频| 亚洲日本成人在线观看| 亚洲欧美日本视频在线观看| 欧美成人免费一级人片100| 国产精品成人一区二区| 亚洲电影免费观看高清完整版在线 | 欧美日韩精品久久久| 国产欧美日韩麻豆91| 99国产精品久久久久老师| 久久久久久久久综合| 夜夜精品视频| 日韩一区二区福利| 日韩视频二区| 欧美激情小视频| 亚洲国产婷婷| 久久亚洲国产精品一区二区| 亚洲视频一起| 国产精品久久久久久久第一福利 | 国产精品腿扒开做爽爽爽挤奶网站| 亚洲人成在线播放| 亚洲国产精品一区在线观看不卡| 久久琪琪电影院| 亚洲久久一区二区| 国产午夜精品美女视频明星a级| 另类春色校园亚洲| 在线日本欧美| 亚洲激情成人| 欧美片第一页| 欧美一区二区三区男人的天堂| 欧美中文在线免费| 亚洲高清av| 亚洲乱码国产乱码精品精| 欧美精品一区二区精品网| 国产精品久久99| 久久精品国产精品| 亚洲一区在线免费| 乱中年女人伦av一区二区| 国产日产高清欧美一区二区三区| 亚洲精品小视频| 亚洲国产欧美在线| 欧美人成网站| 亚洲欧美一区在线| 欧美激情一区二区在线| 欧美第十八页| 小嫩嫩精品导航| 国产精品日韩精品欧美精品| 久久婷婷成人综合色| 国产精品久久看| 久久精品国产久精国产一老狼| 亚洲欧美成人一区二区三区| 国产在线精品一区二区夜色| 免费永久网站黄欧美| 欧美激情在线观看| 香蕉视频成人在线观看 | 欧美在线视频观看免费网站| 久久久久一区二区三区| 亚洲欧美在线aaa| 欧美大胆成人| 久久久久久久久伊人| 欧美日韩1区2区| 欧美成人一区二区| 国产亚洲激情在线|