OIの解釈

# 树链剖分刷水

BZOJ 2836 魔法树

#include <cstdio>
#include <algorithm>
#define FOR(i,j,k) for(i=j;i<=k;i++)
typedef long long ll;
using std::swap;
ll s = 0; char ch = getchar();
for (; ch < '0' || ch > '9'; ch = getchar());
for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';
return s;
}
const int N = 200001, M = N * 2;
int n, id = 0, cnt = 0;
int dep[N], son[N], sz[N], fa[N], top[N], pos[N], end[N];
ll sum[M], lazy[M];

void add(int u, int v) {
}

void dfs1(int x) {
son[x] = 0; sz[x] = 1;
for (int i = head[x]; i; i = next[i])
if (to[i] != fa[x]) {
fa[to[i]] = x; dep[to[i]] = dep[x] + 1;
dfs1(to[i]); sz[x] += sz[to[i]];
if (sz[son[x]] < sz[to[i]]) son[x] = to[i];
}
}

void dfs2(int x, int t) {
top[x] = t; pos[x] = ++id;
if (son[x]) dfs2(son[x], t);
for (int i = head[x]; i; i = next[i])
if (to[i] != son[x] && to[i] != fa[x])
dfs2(to[i], to[i]);
end[x] = id;
}

void update(int t, int l, int r, ll v) {
sum[t] += (r - l + 1) * v; lazy[t] += v;
}

void pushdown(int t, int l, int r) {
int mid = l + r >> 1;
update(t * 2, l, mid, lazy[t]);
update(t * 2 + 1, mid + 1, r, lazy[t]);
lazy[t] = 0;
}

void modify(int t, int l, int r, int ql, int qr, ll plus) {
if (l == ql && r == qr) { update(t, l, r, plus); return; }
pushdown(t, l, r);
int mid = l + r >> 1;
if (qr <= mid) modify(t * 2, l, mid, ql, qr, plus);
else if (ql > mid) modify(t * 2 + 1, mid + 1, r, ql, qr, plus);
else modify(t * 2, l, mid, ql, mid, plus),
modify(t * 2 + 1, mid + 1, r, mid + 1, qr, plus);
sum[t] = sum[t * 2] + sum[t * 2 + 1];
}

ll query(int t, int l, int r, int ql, int qr) {
if (l == ql && r == qr) return sum[t];
pushdown(t, l, r);
int mid = l + r >> 1;
if (qr <= mid) return query(t * 2, l, mid, ql, qr);
else if (ql > mid) return query(t * 2 + 1, mid + 1, r, ql, qr);
else return query(t * 2, l, mid, ql, mid) +
query(t * 2 + 1, mid + 1, r, mid + 1, qr);
}

void treeModify(int x, int y, ll c) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
modify(1, 1, n, pos[fx], pos[x], c);
x = fa[fx], fx = top[x];
}
if (dep[x] > dep[y]) swap(x, y);
modify(1, 1, n, pos[x], pos[y], c);
}

int main() {
int i, x, y, q; ll z; char ch[8];
dfs1(1); dfs2(1, 1);
while (q--) {
scanf("%s", ch);
if (ch[0] == 'A') { // Add
treeModify(x, y, z);
} else { // Query
printf("%lld\n", query(1, 1, n, pos[x], end[x]));
}
}
return 0;
}

## 2836: 魔法树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 152  Solved: 61
[Submit][Status][Discuss]

4
0 1
1 2
2 3
4
Query 0
Query 1
Query 2

## Sample Output

3
3
2

T2 HAOI 2015, BZOJ 4034

#include <cstdio>
#include <algorithm>
#define FOR(i,j,k) for(i=j;i<=k;i++)
typedef long long ll;
using std::swap;
ll s = 0, f = 1; char ch = getchar();
for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';
return s * f;
}
const int N = 200001, M = N * 2;
int n, id = 0, cnt = 0;
int dep[N], son[N], sz[N], fa[N], top[N], pos[N], end[N];
ll sum[M], lazy[M];

void add(int u, int v) {
}

void dfs1(int x) {
son[x] = 0; sz[x] = 1;
for (int i = head[x]; i; i = next[i])
if (to[i] != fa[x]) {
fa[to[i]] = x; dep[to[i]] = dep[x] + 1;
dfs1(to[i]); sz[x] += sz[to[i]];
if (sz[son[x]] < sz[to[i]]) son[x] = to[i];
}
}

void dfs2(int x, int t) {
top[x] = t; pos[x] = ++id;
if (son[x]) dfs2(son[x], t);
for (int i = head[x]; i; i = next[i])
if (to[i] != son[x] && to[i] != fa[x])
dfs2(to[i], to[i]);
end[x] = id;
}

void update(int t, int l, int r, ll v) {
sum[t] += (r - l + 1) * v; lazy[t] += v;
}

void pushdown(int t, int l, int r) {
int mid = l + r >> 1;
update(t * 2, l, mid, lazy[t]);
update(t * 2 + 1, mid + 1, r, lazy[t]);
lazy[t] = 0;
}

void modify(int t, int l, int r, int ql, int qr, ll plus) {
if (l == ql && r == qr) { update(t, l, r, plus); return; }
pushdown(t, l, r);
int mid = l + r >> 1;
if (qr <= mid) modify(t * 2, l, mid, ql, qr, plus);
else if (ql > mid) modify(t * 2 + 1, mid + 1, r, ql, qr, plus);
else modify(t * 2, l, mid, ql, mid, plus),
modify(t * 2 + 1, mid + 1, r, mid + 1, qr, plus);
sum[t] = sum[t * 2] + sum[t * 2 + 1];
}

ll query(int t, int l, int r, int ql, int qr) {
if (l == ql && r == qr) return sum[t];
pushdown(t, l, r);
int mid = l + r >> 1;
if (qr <= mid) return query(t * 2, l, mid, ql, qr);
else if (ql > mid) return query(t * 2 + 1, mid + 1, r, ql, qr);
else return query(t * 2, l, mid, ql, mid) +
query(t * 2 + 1, mid + 1, r, mid + 1, qr);
}

ll treeQuery(int x, int y) {
int fx = top[x], fy = top[y]; ll ans = 0;
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
ans += query(1, 1, n, pos[fx], pos[x]);
x = fa[fx], fx = top[x];
}
if (dep[x] > dep[y]) swap(x, y);
return ans + query(1, 1, n, pos[x], pos[y]);
}

int main() {
static ll w[N];
int i, x, y, q, t;
dfs1(1); dfs2(1, 1);
FOR(i,1,n) modify(1,1,n,pos[i],pos[i],w[i]);
while (q--) {
switch(t) {
case 1:
modify(1, 1, n, pos[x], pos[x], read());
break;
case 2:
modify(1, 1, n, pos[x], end[x], read());
break;
case 3:
printf("%lld\n", treeQuery(1, x));
break;
}
}
return 0;
}

## 4034: [HAOI2015]T2

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 1030  Solved: 356
[Submit][Status][Discuss]

## Description

有一棵点数为 N 的树，以点 1 为根，且树点有边权。然后有 M 个

## Input

第一行包含两个整数 N, M 。表示点数和操作数。

## Output

对于每个询问操作，输出该询问的答案。答案之间用换行隔开。

5 5

1 2 3 4 5

1 2

1 4

2 3

2 5

3 3

1 2 1

3 5

2 1 2

3 3

6

9

13

## HINT

对于 100% 的数据， N,M<=100000 ，且所有输入数据的绝对值都不

Query on a tree SPOJ 375

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.

We will ask you to perfrom some instructions of the following form:

• CHANGE i ti : change the cost of the i-th edge to ti
or
• QUERY a b : ask for the maximum edge cost on the path from node a to node b

### Input

The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.

For each test case:

• In the first line there is an integer N (N <= 10000),
• In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 1000000),
• The next lines contain instructions "CHANGE i ti" or "QUERY a b",
• The end of each test case is signified by the string "DONE".

There is one blank line between successive tests.

### Output

For each "QUERY" operation, write one integer representing its result.

### Example

Input:
1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Output:
1
3
#include <cstdio>
#include <algorithm>
#include <cstring>
#define FOR(i,j,k) for(i=j;i<=k;i++)
using std::swap; using std::max;
int s = 0, f = 1; char ch = getchar();
for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';
return s * f;
}
const int N = 200001, M = N * 2;
int n, id = 0, cnt = 0;
int dep[N], son[N], sz[N], fa[N], top[N], pos[N], end[N];

void add(int u, int v) {
}

void dfs1(int x) {
son[x] = 0; sz[x] = 1;
for (int i = head[x]; i; i = next[i])
if (to[i] != fa[x]) {
fa[to[i]] = x; dep[to[i]] = dep[x] + 1;
dfs1(to[i]); sz[x] += sz[to[i]];
if (sz[son[x]] < sz[to[i]]) son[x] = to[i];
}
}

void dfs2(int x, int t) {
top[x] = t; pos[x] = ++id;
if (son[x]) dfs2(son[x], t);
for (int i = head[x]; i; i = next[i])
if (to[i] != son[x] && to[i] != fa[x])
dfs2(to[i], to[i]);
end[x] = id;
}

void modify(int t, int l, int r, int x, int v) {
if (l == r) { ma[t] = v; return; }
int mid = l + r >> 1;
if (x <= mid) modify(t * 2, l, mid, x, v);
else if (x > mid) modify(t * 2 + 1, mid + 1, r, x, v);
ma[t] = max(ma[t * 2], ma[t * 2 + 1]);
}

int query(int t, int l, int r, int ql, int qr) {
if (l == ql && r == qr) return ma[t];
int mid = l + r >> 1;
if (qr <= mid) return query(t * 2, l, mid, ql, qr);
else if (ql > mid) return query(t * 2 + 1, mid + 1, r, ql, qr);
else return max(query(t * 2, l, mid, ql, mid),
query(t * 2 + 1, mid + 1, r, mid + 1, qr));
}

int treeQuery(int x, int y) {
int fx = top[x], fy = top[y], ans = 0;
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
ans = max(ans, query(1, 1, n, pos[fx], pos[x]));
x = fa[fx], fx = top[x];
}
if (dep[x] > dep[y]) swap(x, y);
return max(ans, query(1, 1, n, pos[x], pos[y]));
}

int main() {
static int a[M], b[M], c[M];
char ch[8];
int i, x, y, z, t;
while (t--) {
memset(ma, 0, sizeof ma);
dfs1(1); dfs2(1, 1);
FOR(i,2,n) {
if (dep[a[i]] > dep[b[i]]) swap(a[i], b[i]);
modify(1, 1, n, pos[b[i]], c[i]);
}
while (1) {
scanf("%s", ch);
if (ch[0] == 'C')
else if (ch[0] == 'Q')
else break;
}
}
return 0;
}

#### SAI水墨笔刷

2014年06月03日 574B 下载

#### 分分梯子刷返水一小时，每天稳赚960元攻略。

2018-05-30 15:02:42

#### 刷水~~~~~~~~~~~

2011-02-07 15:51:00

#### 杨灵华-中国水墨画笔4.0免费版

2014年02月10日 4.33MB 下载

#### 7种水溅水花水浪笔刷

2015年04月12日 784KB 下载

#### 水卡破解,IC卡密码操作工具Accr122u驱动

2016年03月30日 42.06MB 下载

#### 野田圣子、希尔顿、松下幸之助，都喝过马桶水吗？

2014-09-28 14:24:18

#### 树链剖分小结及题目

2016-08-04 10:28:22

#### 树链剖分详解及模板

2014-10-21 17:40:59

#### 树链剖分

2015年09月22日 800KB 下载