這題用線段樹貌似過不了,和nyoj 的士兵殺敵五一樣,經過樹鏈剖分後,就把樹剖分成許多鏈,這樣可以對整個鏈操作,結合字首和的思想,如果某個節點到祖先節點更新這間的所有節點,可以把祖先節點 + k ,讓當前節點編號 + 1 減 k ,這樣最後跑一邊陣列就可以了,葉子節點的時候類似。
#pragma comment(linker, "/stack:1024000000,1024000000")
#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std ;
#define int __int64
#define l(x) (x * 2)
#define r(x) (x * 2 + 1)
const int inf = 0x3f3f3f3f ;
const double esp = 0.0000000001 ;
const double pi = acos(-1.0) ;
const int mod = 1e9 + 7 ;
const int my = 1400 + 5 ;
const int mx = 100000 + 5 ;
int n ,m ,num ,idx ;
int ans1[mx] ,ans2[mx] ,sum[2][mx] ;
int dep[mx] ,top[mx] ,ti[mx] ,pd[mx] ,pe[mx] ,head[mx] ,siz[mx] ,son[mx] ,father[mx] ;
struct node
e[mx] ;
struct edge
e[mx*2] ;
void addedge(int u ,int v)
void dfs_find(int u ,int fa)
}void dfs_time(int u ,int fa)
}void lca(int u ,int v ,int w ,int pos)
if(dep[u] > dep[v]) // u 變為深(大)
swap(u ,v) ;
if(!pos)
else
}void init()
int main()
dep[1] = siz[0] = 0 ;
dfs_find(1 ,1) ;
idx = 1 ;
dfs_time(1 ,1) ;
for(int i = 1 ;i < n ; ++i)
pd[ti[n]] = n ;
char s[10] ;
int u ,v ;
int w ;
for(int i = 0 ;i < m ; ++i)
for(int i = 1 ;i <= n ; ++i) // 表示在剖分中的編號
printf("case #%d:\n" ,cse++) ;
printf("%i64d" ,ans1[1]) ;
for(int i = 2 ;i <= n ; ++i)
printf(" %i64d" ,ans1[i]) ;
puts("") ;
if(n > 1)
printf("%i64d" ,ans2[1]) ;
for(int i = 2 ;i < n ; ++i)
printf(" %i64d" ,ans2[i]) ;
puts("") ;
}return 0 ;
}
HDU 5044 Tree 樹鏈剖分
題意 給一棵樹,兩種操作 add1 給u v路徑上所有點加上值k,add2 給u v路徑上所有邊加上k,初始值都為0,問最後每個點和每條邊的值,輸出。解法 樹鏈剖分可做,剖出來如果直接用線段樹來區間更新的話會tle,所以要換一種姿勢,有一種樹鏈剖分的經典姿勢就是看做樹狀陣列一樣,每次加值的時候,比如...
HDU5044 Tree 樹鏈剖分
大致題意 add1 u v u到v路徑上所有點的權值加上k,add2 u 到v路徑上所有邊的權值加上k 最後輸出所有點的權值,邊的權值。樹鏈剖分預處理然後來個線性o n 的操作。剛開始用線段樹tle了.1 pragma comment linker,stack 1024000000,10240000...
poj3237 Tree 樹鏈剖分
這個題是spoj的改版 是在原來的題意上增加了區間取反操作 所以只需要在spoj375的基礎上再線段樹上增加乙個取反標誌 同時在維護乙個區間最小值 因為在區間取反了以後 區間的最大值就是區間原來的最小值 嗯 就這樣就可以了 include include include using namespac...