HDU 6547 樹鏈剖分

2021-09-26 00:18:00 字數 2288 閱讀 8583

wls 有三棵樹,樹上每個節點都有乙個值 aiai,現在有 2 種操作: 

1. 將一條鏈上的所有節點的值開根號向下取整; 

2. 求一條鏈上值的和; 

鏈的定義是兩點之間的最短路。

input

第一行兩個數 nn, qq 分別代表樹上點的數量和運算元量。 

第二行 nn 個整數,第 ii 個數代表第 ii 個點的值 aiai。 

接下來 nn −− 11 行, 每行兩個整數 uu, vv 代表 uu,vv 之間有一條邊。資料保證點兩兩聯通。 

接下來 qq 行,每行有個整數 opop, uu, vv,opop = 0 表示將 uu, vv 這條鏈上所有的點的值開根號向下取整,opop = 1表示詢問 uu,vv 這條鏈上的值的和。 

1 ≤ nn, qq ≤ 100, 000 

0 ≤ aiai ≤ 1, 000, 000, 000

output

對於每一組 opop = 2 的詢問,輸出一行乙個值表示答案。

sample input

4 4

2 3 4 5

1 22 3

2 40 3 4

0 1 3

1 2 3

1 1 4

sample output

2

4

很明顯,樹鏈剖分的模板題,也沒有什麼特別要注意的地方。唯一的就是rk【】和點權值a【】對映到 id【】上要注意一下

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define  ll long long

#define ull unsigned long long

#define mod 10007

#define inf 0x7ffffff

#define mem(a,b) memset(a,b,sizeof(a))

#define modd(a,b) (((a%b)+b)%b)

using namespace std;

const int maxn = 1e5 + 5;

int head[maxn],cnt,tot,n;

int top[maxn],f[maxn],rk[maxn],id[maxn],sz[maxn],d[maxn],son[maxn];

struct edgee[maxn << 1];

ll sum[maxn << 2],a[maxn];

void add(int u,int v)

void pushup(int rt)

void buildtree(int l,int r,int rt)

int mid = (l + r) >> 1;

buildtree(l,mid,rt << 1);

buildtree(mid + 1,r,rt << 1 | 1);

pushup(rt);

}void dfs1(int u,int fa,int depth)

}void dfs2(int u,int t)

}void update(int l,int r,int l,int r,int rt)

int mid = (l + r) >> 1;

if(l <= mid) update(l,r,l,mid,rt << 1);

if(r > mid) update(l,r,mid + 1,r,rt << 1 | 1);

pushup(rt);

}ll query(int l,int r,int l,int r,int rt)

void uprange(int x,int y)

if(d[x] > d[y]) swap(x,y);

update(id[x],id[y],1,n,1);

}ll queryrange(int x,int y)

if(d[x] > d[y]) swap(x,y);

ans += query(id[x],id[y],1,n,1);

return ans;

}void prework()

int main()

dfs1(1,0,1);

dfs2(1,1);

buildtree(1,n,1);

while(m--)

else if(opt == 1)

}return 0;

}

HDU 6547 樹鏈剖分

大意是一顆有根樹,根節點為1,樹上有兩個操作,乙個是對兩個節點間的節點開根號,乙個是詢問兩個節點間所有節點的權值和 開根號就是暴力對每個節點開根號 因為開根號能很快的接近1 樹鏈剖分解決樹上問題就是把它轉化成線性表,然後再用一些資料結構維護一下就好了。所以說線性表的的增刪查改才是重點 ac incl...

HDU 6547 Tree 樹鏈剖分 線段樹

hdu 6547 tree 給定一顆樹,q次操作,1 詢問樹上任意兩點之間最短路上點權和 2 將樹上任意兩點之間最短路上每個點權開根 樹上路徑問題樹鏈剖分跑不了,考慮怎樣維護區間開根,容易發現0,1開根後不改變值 開根遞減的很快,1e9開5次根後再開根就不變了,那麼就可以每次暴力更新到葉子節點,並且...

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...