BZOJ 2836 魔法树
链改+子树查,和NOI 2015那道差不多吧。。
#include <cstdio>
#include <algorithm>
#define FOR(i,j,k) for(i=j;i<=k;i++)
typedef long long ll;
using std::swap;
ll read() {
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];
int head[N], next[M], to[M];
ll sum[M], lazy[M];
void add(int u, int v) {
next[++cnt] = head[u]; head[u] = cnt; to[cnt] = v;
next[++cnt] = head[v]; head[v] = cnt; to[cnt] = u;
}
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];
n = read();
FOR(i,2,n) add(read()+1, read()+1);
q = read();
dfs1(1); dfs2(1, 1);
while (q--) {
scanf("%s", ch);
if (ch[0] == 'A') { // Add
x = read()+1, y = read()+1, z = read();
treeModify(x, y, z);
} else { // Query
x = read()+1;
printf("%lld\n", query(1, 1, n, pos[x], end[x]));
}
}
return 0;
}
2836: 魔法树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 152 Solved: 61
[ Submit][ Status][ Discuss]
Description
Input
Output
Sample Input
4
0 1
1 2
2 3
4
Add 1 3 1
Query 0
Query 1
Query 2
0 1
1 2
2 3
4
Add 1 3 1
Query 0
Query 1
Query 2
Sample Output
3
3
2
3
2
T2 HAOI 2015, BZOJ 4034
稍微改下就好了。。竟然忘吧快速读入读负数给写回来WA了几次。。真是作死。。
#include <cstdio>
#include <algorithm>
#define FOR(i,j,k) for(i=j;i<=k;i++)
typedef long long ll;
using std::swap;
ll read() {
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];
int head[N], next[M], to[M];
ll sum[M], lazy[M];
void add(int u, int v) {
next[++cnt] = head[u]; head[u] = cnt; to[cnt] = v;
next[++cnt] = head[v]; head[v] = cnt; to[cnt] = u;
}
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;
n = read(), q = read();
FOR(i,1,n) w[i] = read();
FOR(i,2,n) add(read(), read());
dfs1(1); dfs2(1, 1);
FOR(i,1,n) modify(1,1,n,pos[i],pos[i],w[i]);
while (q--) {
t = read(); x = read();
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 MBSubmit: 1030 Solved: 356
[ Submit][ Status][ Discuss]
Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
Input
第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Sample Input
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
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
Sample Output
6
9
13
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。
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 read() {
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];
int head[N], next[M], to[M], ma[M];
void add(int u, int v) {
next[++cnt] = head[u]; head[u] = cnt; to[cnt] = v;
next[++cnt] = head[v]; head[v] = cnt; to[cnt] = u;
}
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;
t = read();
while (t--) {
n = read();
memset(ma, 0, sizeof ma);
memset(head, 0, sizeof head);
FOR(i,2,n) a[i] = read(), b[i] = read(), c[i] = read(), add(a[i], b[i]);
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')
x = read(), y = read(), modify(1, 1, n, pos[b[x]], y);
else if (ch[0] == 'Q')
x = read(), y = read(), printf("%d\n", treeQuery(x, y));
else break;
}
}
return 0;
}