练习地址: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; }