洛谷 P4114 Qtree1 樹鏈剖分

2022-07-16 22:21:16 字數 2226 閱讀 9049

目錄輸入輸出樣例

說明說明

思路ac**

總結p4114 qtree1

給定一棵 $ n $個節點的樹,有兩個操作:

change $ i $ $ t_i $ 把第 $ i $條邊的邊權變成 $ t_i $

query $ a $ $ b $ 輸出從 $ a $ 到 $ b $ 的路徑中最大的邊權,當 $ a=b $ 的時候,輸出 0

第一行輸入乙個 $ n $,表示節點個數

第二行到第 $ n $ 行每行輸入三個數,$ u_i,v_i,w_i $ ,分別表示 $ u_i,v_i $ 有一條邊,邊權是 $ w_i $

第 $ n+1 $ 行開始,一共有不定數量行,每一行分別有以下三種可能

change,query同題意所述

done表示輸入結束

對於每個query操作,輸出乙個數,表示 $ a $ $ b $ 之間邊權最大值

3

1 2 1

2 3 2

query 1 2

change 1 3

query 1 2

done

1

33

【資料範圍】

$1 \leq n \leq 10^5 $

操作次數 $ \leq 3*10^5 $

$ w_i $ 和 $ t_i \leq 2^-1$

【時空限制】

1000ms,512m

熟知的樹鏈剖分是解決點權的問題的,而這一題是邊權。

由於每個點可以有多個兒子,但只有乙個父親,可以考慮將邊權儲存到深度較大的點的點權。這樣n-1條邊的邊權就會對應到n-1個點上,而根節點(這裡以1為根節點)的點權就是0。

再考慮題中兩個操作。

change操作相對簡單。改變兩點之間的邊權,即改動兩點中較深點的點權。

query操作略有改動。查詢兩點間路徑中所有邊的最大邊權,如果查詢所有經過的點是有問題的。先看圖

其中while迴圈不用改變,while迴圈結束後,u和v處於同一條鏈上。

如果u==v,此時u和v都是最初兩點的lca,此時直接返回

否則,u和v之中深度較小的那一點是最初兩點的lca,應該從這個點的重兒子開始統計答案。

故改變後的**如下

int ask(int u,int v)

#includeconst int maxn=100010;

using namespace std;

int n,wt[maxn];

int tot,to[maxn<<1],nxt[maxn<<1],head[maxn];

int dep[maxn],len[maxn],fa[maxn],son[maxn];

int cnt,nid[maxn],nw[maxn],top[maxn];

struct segmenttree

tree[maxn<<2];

void dfs1(int u,int f,int d)

}void dfs2(int p,int t)

}void buildtree(int p,int l,int r)

buildtree(p<<1,l(p),m(p));

buildtree(p<<1|1,m(p)+1,r);

mx(p)=max(mx(p<<1),mx(p<<1|1));

}void change(int np,int p,int k)

if(p<=m(np)) change(np<<1,p,k);

if(p>m(np)) change(np<<1|1,p,k);

mx(np)=max(mx(np<<1),mx(np<<1|1));

}int q(int p,int l,int r)

int ask(int u,int v)

int main()

buildtree(1,1,n);

while(1)

if(way=="query")

}return 0;

}

樹剖處理邊權的板子題

洛谷P3384 樹鏈剖分

這是一道樹鏈剖分的模板題,首先要學會線段樹 dfs 鏈式前向星之類的,不然 打暴力吧 本題很考驗 能力,難度不大,主要是細節繁多。我調了1h 樹鏈剖分的原理不再贅述 詳見 資訊學奧賽一本通 提高版 主要說一下一些容易錯的細節。1 include 2 include 3 include 4 typed...

洛谷 P3372 線段樹 1

今天植樹節,來種一棵線段樹。傳送門如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.求出某區間每乙個數的和 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第 i 個數字表示數列第 i 項的初始值。接下來m行每...

線段樹1 洛谷P3372

如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.求出某區間每乙個數的和 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數,表示乙個操作,具體如下...