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

原題地址
【有關(guān)樹的路徑剖分的東東在網(wǎng)上介紹的太多了……】
常見的路徑剖分的方法是輕重邊剖分,即把樹中的邊分為輕重兩部分,方法:設(shè)SZ[i]為以i為根的子樹的大小(結(jié)點(diǎn)總數(shù)),則若點(diǎn)x不是葉結(jié)點(diǎn),則其子結(jié)點(diǎn)中SZ值最大的(注意,有多個(gè)SZ值最大的子結(jié)點(diǎn)應(yīng)任選一個(gè),只能選一個(gè),防止出現(xiàn)重鏈相交,引發(fā)歧義)點(diǎn)y,邊(x, y)稱為重邊,其余的邊都是輕邊。首尾相連的重邊稱為重鏈(注意一定是自上而下的),則一個(gè)很顯然的性質(zhì)是:從根結(jié)點(diǎn)到任意點(diǎn)i路徑上的輕邊與重鏈的總數(shù)都不會(huì)超過O(log2N)。然后,對(duì)每條重鏈上的邊建立線段樹,每當(dāng)遇到改值操作,若是輕邊就直接改,若是重邊就在線段樹里改;遇到找x、y路徑上邊權(quán)最大值的操作,只要找到LCA(x, y),然后從x、y開始沿著樹邊上溯到LCA(x, y)處,對(duì)于中間的每條輕邊和重鏈(線段樹內(nèi))導(dǎo)出最大值即可。

求LCA:可以對(duì)整棵樹作深度優(yōu)先遍歷,記下每個(gè)遇到的點(diǎn)(包括向上的和向下的)的編號(hào),形成一個(gè)長度為2(N-1)的序列A,然后,找到點(diǎn)x、y在A中的第一次出現(xiàn)的位置(設(shè)為FF[x]和FF[y]),則A[FF[x]..FF[y]]中的深度最小的點(diǎn)的編號(hào)就是LCA(x, y),顯然這需要RMQ。

具體步驟:
(1)輸入部分:建立無根樹;
(2)預(yù)處理部分:分為6步:
<1>利用BFS將無根樹轉(zhuǎn)化為有根樹,同時(shí)求出有根樹中點(diǎn)i(根結(jié)點(diǎn)除外)到其父結(jié)點(diǎn)的邊的編號(hào)(設(shè)為FA[i])以及點(diǎn)i的深度(設(shè)為DEP[i]);
<2>自底向上計(jì)算每個(gè)點(diǎn)的SZ值,同時(shí)劃分輕重邊(對(duì)于有根樹中的每條邊設(shè)立Z域,Z=1為重邊,Z=0為輕邊);
<3>求出重鏈,建立線段樹:
求重鏈的方法:由于重鏈只會(huì)在葉結(jié)點(diǎn)處結(jié)束,因此從每個(gè)葉結(jié)點(diǎn)開始上溯,直到上溯到根或者遇到輕邊為止。為了方便,需要對(duì)每個(gè)結(jié)點(diǎn)i記錄以下4個(gè)值:UP[i]表示點(diǎn)i所在重鏈最頂上的那個(gè)結(jié)點(diǎn)的編號(hào);ord[i]表示點(diǎn)i是其所在重鏈的上起第幾個(gè)點(diǎn)(從0開始);tot[i]表示點(diǎn)i所在重鏈上有幾個(gè)結(jié)點(diǎn);root[i]表示點(diǎn)i所在重鏈建成的線段樹的編號(hào)(這樣經(jīng)常寫的opr(0, n-1, root)就可以表示成opr(0, tot[i]-1, root[i]))。求出重鏈以后,對(duì)沿途經(jīng)歷的所有邊的權(quán)值倒序寫入數(shù)組W0,再對(duì)數(shù)組W0建線段樹即可。考慮到不同線段樹的大小可能不同,這里采用壓縮處理,這樣就需要記錄每個(gè)點(diǎn)的lch、rch編號(hào)(見代碼);
<4>對(duì)樹進(jìn)行DFS遍歷,求出序列A;
<5>求出序列A的倍增最小值,存放在A0[][]里(注意:A和A0中記載的都是編號(hào),而判定大小的關(guān)鍵字是深度);
<6>求出LOG[i]=log2i(下取整);
(3)執(zhí)行部分:對(duì)于詢問操作,求LCA,不斷上溯,對(duì)于重鏈在線段樹里找即可,注意線段樹的左右端點(diǎn),尤其是當(dāng)UP在LCA之上時(shí),只能上溯到LCA處。

編程注意事項(xiàng):建代碼中標(biāo)Attention的地方。
代碼(我這個(gè)代碼常數(shù)巨大,時(shí)間達(dá)3.61s,不知是腫么搞得,神犇來看一下啊囧):
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
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--)
const int MAXN = 10001, MAXS = 20, INF = ~0U >> 2;
struct edge {
    
int a, b, w, pre, next;
    
bool Z;
} E0[MAXN 
<< 2], E[MAXN + MAXN + 1];
struct node {
    
int maxv, lch, rch;
} T[MAXN 
<< 2];
int n, m0, m, N, _a[MAXN], _b[MAXN], FA[MAXN], Q[MAXN], SZ[MAXN], DEP[MAXN], W0[MAXN], UP[MAXN], ord[MAXN], root[MAXN], tot[MAXN];
int n1, stk[MAXN], st[MAXN], A[MAXN << 2], A0[MAXN << 2][MAXS], FF[MAXN], LOG[MAXN << 2], l0, r0, x0, res;
bool vst[MAXN];
void init_d()
{
    re(i, n) E0[i].pre 
= E0[i].next = E[i].pre = E[i].next = i;
    m0 
= m = n;
}
void add_edge0(int a, int b, int w)
{
    E0[m0].a 
= a; E0[m0].b = b; E0[m0].w = w; E0[m0].pre = E0[a].pre; E0[m0].next = a; E0[a].pre = m0; E0[E0[m0].pre].next = m0++;
    E0[m0].a 
= b; E0[m0].b = a; E0[m0].w = w; E0[m0].pre = E0[b].pre; E0[m0].next = b; E0[b].pre = m0; E0[E0[m0].pre].next = m0++;
}
void add_edge(int a, int b, int w)
{
    E[m].a 
= a; E[m].b = b; E[m].w = w; E[m].Z = 0; E[m].pre = E[a].pre; E[m].next = a; E[a].pre = m; E[E[m].pre].next = m++;
}
int mkt(int l, int r)
{
    
int No = ++N;
    
if (l == r) {
        T[No].maxv 
= W0[l]; T[No].lch = T[No].rch = 0;
    } 
else {
        
int mid = l + r >> 1, l_r = mkt(l, mid), r_r = mkt(mid + 1, r); T[No].lch = l_r; T[No].rch = r_r;
        
if (T[l_r].maxv >= T[r_r].maxv) T[No].maxv = T[l_r].maxv; else T[No].maxv = T[r_r].maxv;
    }
    
return No;
}
void prepare()
{
    re(i, n) vst[i] 
= 0; Q[0= 0; vst[0= 1; DEP[0= 0; FA[0= -1;
    
int i0, j0;
    
for (int front=0, rear=0; front<=rear; front++) {
        i0 
= Q[front];
        
for (int p=E0[i0].next; p != i0; p=E0[p].next) {
            j0 
= E0[p].b;
            
if (!vst[j0]) {add_edge(i0, j0, E0[p].w); vst[j0] = 1; Q[++rear] = j0; FA[j0] = m - 1; DEP[j0] = DEP[i0] + 1;}
        }
    }
    
int maxSZ, x, n0, root0;
    rre(i, n) {
        i0 
= Q[i]; SZ[i0] = 1; maxSZ = 0;
        
for (int p=E[i0].next; p != i0; p=E[p].next) {SZ[i0] += SZ[j0 = E[p].b]; if (SZ[j0] > maxSZ) {maxSZ = SZ[j0]; x = p;}}
        
if (SZ[i0] > 1) E[x].Z = 1;   //Attention
    }
    UP[
0= 0; ord[0= 0; N = 0;
    re2(i, 
1, n) {
        i0 
= Q[i]; x = FA[i0]; if (E[x].Z) {UP[i0] = UP[E[x].a]; ord[i0] = ord[E[x].a] + 1;} else {UP[i0] = i0; ord[i0] = 0;}
        
if (SZ[i0] == 1 && ord[i0]) {
            j0 
= UP[i0]; n0 = ord[i0];
            
for (int j=i0; j!=j0; j=E[FA[j]].a) {tot[j] = ord[i0]; W0[--n0] = E[FA[j]].w;} tot[j0] = ord[i0];  //Attention
            root0 = mkt(0, ord[i0] - 1);  //Attention
            for (int j=i0; j!=j0; j=E[FA[j]].a) root[j] = root0; root[j0] = root0;  //Attention
        }
    }
    re(i, n) {st[i] 
= E[i].next; FF[i] = -1;} stk[0= 0int tp = 0; n1 = 1; A[0= FF[0= 0;
    
while (tp >= 0) {
        i0 
= stk[tp]; x = st[i0];
        
if (x != i0) {
            j0 
= E[x].b; if (FF[j0] == -1) FF[j0] = n1; A[n1++= j0; st[i0] = E[x].next; stk[++tp] = j0;
        } 
else {
            
if (tp) A[n1++= stk[tp - 1];
            tp
--;
        }
    }
    rre(i, n1) {
        A0[i][
0= A[i]; x = 1;
        re2(j, 
1, MAXS) if (i + (x << 1<= n1) {
            
if (DEP[A0[i][j - 1]] <= DEP[A0[i + x][j - 1]]) A0[i][j] = A0[i][j - 1]; else A0[i][j] = A0[i + x][j - 1];  //Attention
            x <<= 1;
        } 
else break;
    }
    
int _x; x = 1;
    re(i, MAXS) {
        _x 
= x << 1;
        
if (_x < n1) re2(j, x, _x) LOG[j] = i; else {re2(j, x, n1) LOG[j] = i; break;}
        x 
= _x;
    }
}
void opr0(int l, int r, int No)
{
    
if (l == l0 && r == l0) T[No].maxv = x0; else {
        
int mid = l + r >> 1, lch = T[No].lch, rch = T[No].rch;
        
if (mid >= l0) opr0(l, mid, lch);
        
if (mid < l0) opr0(mid + 1, r, rch);
        
if (T[lch].maxv >= T[rch].maxv) T[No].maxv = T[lch].maxv; else T[No].maxv = T[rch].maxv;
    }
}
void opr1(int l, int r, int No)
{
    
if (l >= l0 && r <= r0) {
        
if (T[No].maxv > res) res = T[No].maxv;
    } 
else {
        
int mid = l + r >> 1;
        
if (mid >= l0) opr1(l, mid, T[No].lch);
        
if (mid < r0) opr1(mid + 1, r, T[No].rch);
    }
}
int main()
{
    
int tests, a0, b0, w0, LCA, LOG0, FF0, FF1, p0, tmp;
    
char ss[20], ch;
    scanf(
"%d"&tests);
    re(testno, tests) {
        scanf(
"%d"&n); init_d();
        re(i, n
-1) {scanf("%d%d%d"&a0, &b0, &w0); add_edge0(--a0, --b0, w0); _a[i] = a0; _b[i] = b0;}
        prepare(); ch 
= getchar();
        
while (1) {
            scanf(
"%s", ss);
            
if (!strcmp(ss, "QUERY")) {
                scanf(
"%d%d%*c"&a0, &b0); --a0; --b0;
                
if (a0 == b0) res = 0else res = -INF;
                FF0 
= FF[a0]; FF1 = FF[b0];
                
if (FF0 > FF1) {tmp = FF0; FF0 = FF1; FF1 = tmp;}
                LOG0 
= LOG[FF1 - FF0 + 1];
                
if (DEP[A0[FF0][LOG0]] <= DEP[A0[FF1 - (1 << LOG0) + 1][LOG0]]) LCA = A0[FF0][LOG0]; else LCA = A0[FF1 - (1 << LOG0) + 1][LOG0];
                
while (a0 != LCA) {
                    p0 
= FA[a0];
                    
if (E[p0].Z) {
                        r0 
= ord[a0] - 1if (DEP[UP[a0]] >= DEP[LCA]) l0 = 0else l0 = ord[LCA];  //Attention
                        if (l0 <= r0) opr1(0, tot[a0] - 1, root[a0]);  //Attention
                        if (l0) a0 = LCA; else a0 = UP[a0];
                    } 
else {
                        
if (E[p0].w > res) res = E[p0].w;
                        a0 
= E[p0].a;
                    }
                }
                
while (b0 != LCA) {
                    p0 
= FA[b0];
                    
if (E[p0].Z) {
                        r0 
= ord[b0] - 1if (DEP[UP[b0]] >= DEP[LCA]) l0 = 0else l0 = ord[LCA];  //Attention
                        if (l0 <= r0) opr1(0, tot[b0] - 1, root[b0]);  //Attention
                        if (l0) b0 = LCA; else b0 = UP[b0];
                    } 
else {
                        
if (E[p0].w > res) res = E[p0].w;
                        b0 
= E[p0].a;
                    }
                }
                printf(
"%d\n", res);
            } 
else if (!strcmp(ss, "CHANGE")) {
                scanf(
"%d%d"&a0, &w0); b0 = _b[--a0]; a0 = _a[a0];
                
if (FA[b0] == -1 || E[FA[b0]].a != a0) {tmp = a0; a0 = b0; b0 = tmp;}
                p0 
= FA[b0];
                
if (E[p0].Z) {
                    l0 
= ord[a0]; x0 = w0; opr0(0, tot[a0] - 1, root[a0]);
                } 
else E[p0].w = w0;
            } 
else break;
        }
    }
    
return 0;
}
樹的路徑剖分是解決樹上路徑的操作查詢問題的有力工具,它還有一些更為強(qiáng)大的應(yīng)用,以后再來搞……

Feedback

# re: QTREE——樹的路徑剖分(又稱樹鏈剖分)[未登錄]  回復(fù)  更多評(píng)論   

2012-08-14 00:11 by 楊楊
對(duì)于修改操作,不一定需要使用LCA
直接貼別人的話:
http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
修改操作:例如將u到v的路徑上每條邊的權(quán)值都加上某值x。
一般人需要先求LCA,然后慢慢修改u、v到公共祖先的邊。而高手就不需要了。
記f1 = top[u],f2 = top[v]。
當(dāng)f1 <> f2時(shí):不妨設(shè)dep[f1] >= dep[f2],那么就更新u到f1的父邊的權(quán)值(logn),并使u = fa[f1]。
當(dāng)f1 = f2時(shí):u與v在同一條重鏈上,若u與v不是同一點(diǎn),就更新u到v路徑上的邊的權(quán)值(logn),否則修改完成;
重復(fù)上述過程,直到修改完成

比使用LCA快

# re: QTREE——樹的路徑剖分(又稱樹鏈剖分)  回復(fù)  更多評(píng)論   

2012-10-25 20:43 by Mato_No1
@楊楊
這個(gè)其實(shí)就是WJMZBMR自創(chuàng)的那種利用路徑剖分求LCA的算法,見http://www.shnenglu.com/MatoNo1/archive/2012/01/14/164163.html
只不過這個(gè)是在求LCA的過程中順便操作了而已
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            一区二区三区.www| 国产一区欧美| 亚洲女性喷水在线观看一区| 最新成人av在线| 亚洲高清自拍| 亚洲日本无吗高清不卡| 9i看片成人免费高清| 亚洲深夜福利网站| 午夜视频一区二区| 久久综合五月| 欧美精品国产精品日韩精品| 欧美午夜无遮挡| 国产日韩一区| 日韩小视频在线观看| 先锋影音网一区二区| 免费视频一区| 亚洲一级片在线观看| 久久久久久久网站| 欧美天堂亚洲电影院在线观看| 国产欧美日韩视频| 亚洲国产精品成人久久综合一区| 日韩视频在线观看| 久久天天躁狠狠躁夜夜爽蜜月| 欧美黑人国产人伦爽爽爽| 99在线精品免费视频九九视| 小处雏高清一区二区三区| 蜜桃久久av一区| 国产精品资源在线观看| 亚洲美女av网站| 久久久7777| 一本久久a久久精品亚洲| 久久一区二区三区av| 国产精品爱久久久久久久| 伊人激情综合| 午夜一区在线| 日韩亚洲欧美综合| 欧美成人免费在线观看| 国内精品免费午夜毛片| 亚洲欧美日韩天堂| 99精品国产99久久久久久福利| 浪潮色综合久久天堂| 国产一区在线视频| 欧美一区二区在线看| 一区二区三区不卡视频在线观看 | 麻豆精品精华液| 亚洲已满18点击进入久久| 欧美激情第4页| 亚洲国产午夜| 蜜桃av一区| 久久精品国产2020观看福利| 国产精品中文字幕在线观看| 亚洲在线免费| 亚洲黄色免费电影| 久久精品国产精品| 亚洲免费伊人电影在线观看av| 欧美激情中文字幕一区二区| 亚洲第一在线综合网站| 久久中文字幕一区二区三区| 午夜精品一区二区三区在线视| 国产精品v亚洲精品v日韩精品 | 国产精品美女一区二区| 一区二区三区.www| 最近中文字幕日韩精品| 欧美大片免费观看| 日韩视频三区| 99热这里只有成人精品国产| 欧美性猛交视频| 亚洲欧美日韩国产综合在线 | 亚洲激情另类| 亚洲国产精品传媒在线观看| 蜜桃精品久久久久久久免费影院| 亚洲黄色成人| 一区二区精品在线观看| 国产精品久久久久久久久| 亚洲欧美日韩专区| 欧美在线免费观看| 亚洲精品乱码久久久久久久久| 欧美激情一区二区三级高清视频| 欧美电影美腿模特1979在线看| 妖精成人www高清在线观看| 一区二区三区免费观看| 国产欧美一区二区三区视频 | 亚洲综合色婷婷| 激情91久久| 亚洲另类视频| 国产日韩精品久久久| 欧美成人久久| 欧美性天天影院| 久久久久久亚洲精品杨幂换脸| 久久在线视频在线| 一区二区三区国产盗摄| 亚洲欧美在线视频观看| 在线观看欧美激情| 亚洲麻豆av| 国产手机视频一区二区| 91久久精品久久国产性色也91| 国产精品久久久久久久久久久久| 久久在线免费| 国产精品久久久久影院亚瑟 | 性色一区二区三区| 亚洲精品中文字| 午夜精品一区二区三区在线| 亚洲片在线资源| 午夜视频在线观看一区| 99热在线精品观看| 免费亚洲一区| 国产精品久久久久久久一区探花| 久久亚洲精品网站| 国产精品免费网站| 亚洲激情在线| 亚洲高清在线| 欧美一区二区播放| 亚洲欧美日韩一区二区| 欧美激情一区二区三区在线视频| 欧美一区二区免费| 欧美日韩一区二区免费在线观看| 久久婷婷久久一区二区三区| 欧美天堂亚洲电影院在线观看| 欧美福利专区| 精品成人一区二区三区四区| 亚洲一区高清| 亚洲色图制服丝袜| 欧美精品三级| 亚洲韩日在线| 日韩视频免费看| 欧美成人综合在线| 欧美激情一区二区三区成人| 国产在线高清精品| 亚洲欧美www| 午夜精品一区二区三区四区| 欧美午夜免费影院| 亚洲天堂偷拍| 欧美一区三区二区在线观看| 欧美亚洲在线观看| 免费久久久一本精品久久区| 久久综合色婷婷| 狠狠色综合网| 久久综合久久综合这里只有精品 | 久久精品国产免费观看| 久久国产精彩视频| 国内外成人免费激情在线视频网站| 亚洲一区二区免费在线| 亚洲欧美日韩国产综合| 国产精品午夜在线| 欧美一级精品大片| 久久一二三四| 亚洲裸体在线观看| 欧美日韩一区二区三区四区五区 | 国产精品日韩电影| 午夜一区在线| 久久日韩精品| 亚洲精品色婷婷福利天堂| 欧美日韩精品免费看| 正在播放亚洲一区| 久久国产欧美精品| 亚洲第一精品在线| 欧美日韩国产色视频| 亚洲一区二区三区四区在线观看| 午夜在线视频观看日韩17c| 国产亚洲精品一区二区| 久久久最新网址| 99精品视频免费全部在线| 久久国产精品一区二区三区| 亚洲国内高清视频| 国产精品亚洲美女av网站| 久久频这里精品99香蕉| 日韩视频在线你懂得| 久久久精品国产99久久精品芒果| 国产亚洲在线| 欧美成人国产va精品日本一级| 亚洲人成人99网站| 国产精品白丝av嫩草影院| 欧美中文字幕在线播放| 亚洲国产日日夜夜| 亚洲欧美日韩一区在线观看| 国产一区二区三区的电影| 欧美电影免费观看网站| 亚洲自拍偷拍视频| 欧美国产第一页| 性做久久久久久久久| 亚洲国产成人tv| 国产精品视区| 欧美精品久久一区| 久久精品国语| 亚洲女爱视频在线| 亚洲精选久久| 免费日韩视频| 久久久噜噜噜久久人人看| 亚洲天堂av综合网| 亚洲精品美女| 亚洲高清在线精品| 好看的亚洲午夜视频在线| 国产精品久久久久久久7电影| 免费h精品视频在线播放| 性色一区二区三区| 宅男噜噜噜66国产日韩在线观看| 亚洲成色777777女色窝| 久热精品视频在线观看一区| 翔田千里一区二区| 亚洲一区二区三区午夜|