HDU 6394 Tree(樹分塊 倍增)

2022-07-17 20:18:10 字數 1901 閱讀 4246

給出一棵樹,然後每個節點有乙個權值,代表這個點可以往上面跳多遠,問最少需要多少次可以跳出這顆樹

先dfs一次得到dfs序,然後按dfs序分塊。倍增計算從某點跳x到哪個點,用cn儲存它跳出這一塊需要的次數,ne儲存跳出這塊會去的點。然後塊內就暴力修改了。複雜度nsqrt(n);

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;typedef unsigned

long

long

ull;

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

#define pb push_back

#define mp make_pair

#define pii pair#define eps 0.0000000001

#define ios ios::sync_with_stdio(0);cin.tie(0);

#define random(a, b) rand()*rand()%(b-a+1)+a

#define pi acos(-1)

const ll inf =0x3f3f3f3f3f3f3f3fll;

const

int inf = 0x3f3f3f3f

;const

int maxn = 1e5 + 10

;const

int maxm = 200000 + 10

;const

int mod = 998244353

;int w[maxn],fa[20

][maxn],n,m;

inthead[maxn],nxt[maxn],to[maxn],tot;

int id[maxn],cnt;//

dfs序

int num,block,belong[maxn],l[maxn],r[maxn];//

塊的數目,快的大小,屬於那塊,每塊的左右邊界

int cn[maxn],ne[maxn],pre[maxn];//

跳出本塊的次數,跳向的下一塊的點,這個點會跳向的位置

void

init()

void addedge(int u,int

v)void dfs1(int u,int f)

}void build()

for(int i=1;i<=num;i++)

r[num]=n;

}int find(int u,int

l) }

returnu;}

void dfs2(int u)

}int query(int

u)

return

ans;

}void update(int u,int

val)

}}int

main()

for(int i=1;i<=n;i++)

dfs1(

1,0);

for(int i=1;i<20;i++)

}build();

dfs2(1);

scanf("%d

",&m);

while(m--)

else}}

return0;

}

HDU 5044 Tree 樹鏈剖分

題意 給一棵樹,兩種操作 add1 給u v路徑上所有點加上值k,add2 給u v路徑上所有邊加上k,初始值都為0,問最後每個點和每條邊的值,輸出。解法 樹鏈剖分可做,剖出來如果直接用線段樹來區間更新的話會tle,所以要換一種姿勢,有一種樹鏈剖分的經典姿勢就是看做樹狀陣列一樣,每次加值的時候,比如...

HDU 5044 Tree (樹鏈剖分)

這題用線段樹貌似過不了,和nyoj 的士兵殺敵五一樣,經過樹鏈剖分後,就把樹剖分成許多鏈,這樣可以對整個鏈操作,結合字首和的思想,如果某個節點到祖先節點更新這間的所有節點,可以把祖先節點 k 讓當前節點編號 1 減 k 這樣最後跑一邊陣列就可以了,葉子節點的時候類似。pragma comment l...

HDU5044 Tree 樹鏈剖分

大致題意 add1 u v u到v路徑上所有點的權值加上k,add2 u 到v路徑上所有邊的權值加上k 最後輸出所有點的權值,邊的權值。樹鏈剖分預處理然後來個線性o n 的操作。剛開始用線段樹tle了.1 pragma comment linker,stack 1024000000,10240000...