大致題意:add1 u v u到v路徑上所有點的權值加上k,add2 u 到v路徑上所有邊的權值加上k
最後輸出所有點的權值,邊的權值。。樹鏈剖分預處理然後來個線性o(n)的操作。剛開始用線段樹tle了.
1view code#pragma comment(linker, "/stack:1024000000,1024000000")
2 #include 3 #include 4 #include 5 #include 6 #include 7
using
namespace
std;
8 typedef unsigned long
long
ull;
9 typedef long
long
ll;10
const
int inf = 0x3f3f3f3f;11
const
int maxn = 1e5+10;12
struct
13 e[maxn<<1
];16
inthead[maxn],edge;
17void add(int x,int
y)18
2324
intson[maxn],fa[maxn],siz[maxn],dep[maxn];
25void dfs1(int
root)
2640}41
}42inttop[maxn],pos[maxn],fp[maxn],tot;
43void dfs2(int root,int
f)44
54 ll addv[3][maxn<<2
];55
intk;
56void pre_update(int ua,int ub,int
cho)
5769
if (dep[ua] >dep[ub])
70swap(ua,ub);
71if (cho == 1
)72 addv[cho][pos[ua]] += k,addv[cho][pos[ub]+1] -=k;
73if (cho == 2
)74 addv[cho][pos[son[ua]]] += k,addv[cho][pos[ub]+1] -=k;75}
76int n,m,d[maxn][2
],link[maxn];
77void
init()
7894
dfs1(root);
95dfs2(root,root);
96for (int i = 1; i < n; i++)
97102
}103
ll ans1[maxn],ans2[maxn];
104int main(void
)105
120for (int i = 1; i <= n; i++)
121127 printf("
case #%d:\n
",cas++);
128 printf("
%i64d
",ans1[1
]);129
for (int i = 2; i <= n; i++)
130133 printf("\n"
);134
if (n>1
)135 printf("
%i64d
",ans2[1
]);136
for (int i = 2; i < n; i++)
137140 printf("\n"
);141
}142
return0;
143 }
HDU 5044 Tree 樹鏈剖分
題意 給一棵樹,兩種操作 add1 給u v路徑上所有點加上值k,add2 給u v路徑上所有邊加上k,初始值都為0,問最後每個點和每條邊的值,輸出。解法 樹鏈剖分可做,剖出來如果直接用線段樹來區間更新的話會tle,所以要換一種姿勢,有一種樹鏈剖分的經典姿勢就是看做樹狀陣列一樣,每次加值的時候,比如...
HDU 5044 Tree (樹鏈剖分)
這題用線段樹貌似過不了,和nyoj 的士兵殺敵五一樣,經過樹鏈剖分後,就把樹剖分成許多鏈,這樣可以對整個鏈操作,結合字首和的思想,如果某個節點到祖先節點更新這間的所有節點,可以把祖先節點 k 讓當前節點編號 1 減 k 這樣最後跑一邊陣列就可以了,葉子節點的時候類似。pragma comment l...
poj3237 Tree 樹鏈剖分
這個題是spoj的改版 是在原來的題意上增加了區間取反操作 所以只需要在spoj375的基礎上再線段樹上增加乙個取反標誌 同時在維護乙個區間最小值 因為在區間取反了以後 區間的最大值就是區間原來的最小值 嗯 就這樣就可以了 include include include using namespac...