练习地址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#overview
以下为我的AC代码
A
树链剖分+线段树区间更新求单点值
//@ScratchingBear g++
#include <cstdio>
#include <vector>
#include <cstring>
#define maxn 100010
using namespace std;
int link[maxn], tot;
int dep[maxn], fa[maxn], son[maxn], siz[maxn], top[maxn], w[maxn];
vector<int>edg[maxn];
void dfs1(int u){
siz[u] = 1; son[u] = 0;
for(int i=0;i<edg[u].size();i++)if(edg[u][i] != fa[u]){
fa[edg[u][i]] = u;
dep[edg[u][i]] = dep[u] + 1;
dfs1(edg[u][i]);
if(siz[edg[u][i]] > siz[son[u]])
son[u] = edg[u][i];
siz[u] += siz[edg[u][i]];
}
}
void dfs2(int u, int tp){
top[u] = tp;
w[u] = ++tot;
link[tot] = u;
if(son[u] == 0) return ;
dfs2(son[u], tp);
for(int i=0;i<edg[u].size();i++)
if(edg[u][i] != son[u] && edg[u][i] != fa[u]){
dfs2(edg[u][i], edg[u][i]);
}
}
//以上为树链剖分部分
struct Node{
int l, r;
int sum;
};
Node tree[maxn * 4];
int num[maxn];
void build_tree(int id, int l, int r){
tree[id].l = l;
tree[id].r = r;
tree[id].sum = 0;
if(l != r){
int mid = (l + r) / 2;
build_tree(id * 2, l, mid);
build_tree(id * 2 + 1, mid + 1, r);
}
}
void update(int id, int l, int r, int val){
if(tree[id].l >= l && tree[id].r <= r) {
tree[id].sum += val;
return ;
}
if(tree[id].l > r || tree[id].r < l) return ;
update(id * 2, l, r, val);
update(id * 2 + 1, l, r, val);
}
int ask(int id, int pos){
int ans = 0;
while(true){
ans += tree[id].sum;
if(tree[id].l == tree[id].r) break;
int mid = (tree[id].l + tree[id].r) / 2;
if(pos <= mid) id *= 2;
else id = id * 2 + 1;
}
// you know ....
return ans + num[link[pos]];
}
void add_val(int x, int y, int val){ //熟练剖分的具体使用
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, w[top[x]], w[x], val);
x = fa[top[x]];
}
if(w[x] > w[y]) swap(x, y);
update(1, w[x], w[y], val);
}
int n, m, p, c1, c2, k;
char str[5];
int main(){
while(scanf("%d %d %d", &n, &m, &p) != EOF){
for(int i=1;i<=n;i++) scanf("%d", &num[i]);
int u, v;
for(int i=1;i<=n;i++){
edg[i].clear();
fa[i] = -1;
}
for(int i=0;i<m;i++){
scanf("%d %d", &u, &v);
edg[u].push_back(v);
edg[v].push_back(u);
}
tot = 0;
fa[1] = 1;
siz[0] = 0;
dep[1] = 1;
dfs1(1);
dfs2(1, 1);
build_tree(1, 1, n);
while(p--){
scanf("%s", str);
if(str[0] == 'I'){
scanf("%d %d %d", &c1, &c2, &k);
add_val(c1, c2, k);
}
else if(str[0] == 'D'){
scanf("%d %d %d", &c1, &c2, &k);
add_val(c1, c2, -k);
}
else{
scanf("%d", &c1);
printf("%d\n", ask(1, w[c1]));
}
}
}
return 0;
}
I
树链剖分+线段树单点更新区间求最大值
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define maxn 100010
using namespace std;
struct Node{
int l, r, val;
}tree[maxn * 4];
void build_tree(int id, int l, int r){
tree[id].l = l;
tree[id].r = r;
tree[id].val = 0;
if(l != r){
int mid = (l + r) / 2;
build_tree(id * 2, l, mid);
build_tree(id * 2 + 1, mid + 1, r);
}
}
void updata(int pos, int val){
int id = 1;
while(tree[id].l != tree[id].r){
int mid = (tree[id].l + tree[id].r) / 2;
if(pos <= mid) id *= 2;
else id = id * 2 + 1;
}
tree[id].val = val;
while(id > 1){
id /= 2;
tree[id].val = max(tree[id * 2].val, tree[id * 2 + 1].val);
}
}
int ask(int id, int ls, int rs){
if(tree[id].l >= ls && tree[id].r <= rs) return tree[id].val;
if(tree[id].l > rs || tree[id].r < ls) return 0;
return max(ask(id * 2, ls, rs), ask(id * 2 + 1, ls, rs));
}
int link[maxn], ids;
int dep[maxn], fa[maxn], son[maxn], siz[maxn], top[maxn];
vector<int>edg[maxn];
void dfs1(int u){
siz[u] = 1; son[u] = 0;
for(int i=0;i<edg[u].size();i++) if(edg[u][i] != fa[u]){
fa[edg[u][i]] = u;
dep[edg[u][i]] = dep[u] + 1;
dfs1(edg[u][i]);
siz[u] += siz[edg[u][i]];
if(siz[edg[u][i]] > siz[son[u]])
son[u] = edg[u][i];
}
}
void dfs2(int u, int tp){
top[u] = tp;
link[u] = ids++;
if(son[u] == 0) return ;
dfs2(son[u], tp);
for(int i=0;i<edg[u].size();i++){
if(edg[u][i] != son[u] && edg[u][i] != fa[u])
dfs2(edg[u][i], edg[u][i]);
}
}
int T, n, u[maxn], v[maxn], ws[maxn];
char str[10];
void ChangeVal(int id, int val){
if(fa[u[id]] == v[id]) swap(u[id], v[id]);
updata(link[v[id]], val);
}
int AskMax(int x, int y){
int ans = 0;
while(top[x] != top[y]){
if(dep[top[x]] > dep[top[y]]) swap(x, y);
ans = max(ans, ask(1, link[top[y]], link[y]));
y = fa[top[y]];
}
if(x == y) return ans;
if(dep[x] > dep[y]) swap(x, y);
return max(ans, ask(1, link[son[x]], link[y]));
}
int main(){
scanf("%d", &T);
while(T--){
scanf("%d", &n);
for(int i=1;i<=n;i++) edg[i].clear();
for(int i=1;i<n;i++){
scanf("%d %d %d", &u[i], &v[i], &ws[i]);
edg[u[i]].push_back(v[i]);
edg[v[i]].push_back(u[i]);
fa[i] = -1;
}
ids = 1; fa[n] = -1;
siz[0] = 0; dep[1] = 1;
dfs1(1);
dfs2(1, 1);
build_tree(1, 1, n);
for(int i=1;i<n;i++) ChangeVal(i, ws[i]);
int x, y;
while(true){
scanf("%s", str);
if(str[0] == 'D') break;
if(str[0] == 'C'){
scanf("%d %d", &x, &y);
ChangeVal(x, y);
}
else{
scanf("%d %d", &x, &y);
printf("%d\n", AskMax(x, y));
}
}
}
return 0;
}