您的位置:首页 > 其它

树链剖分刷水

2015-11-21 11:50 369 查看
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
, son
, sz
, fa
, top
, pos
, end
;
int head
, 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 MB
Submit: 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

Sample Output

3

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
, son
, sz
, fa
, top
, pos
, end
;
int head
, 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
;
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 MB
Submit: 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

Sample Output

6

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
, son
, sz
, fa
, top
, pos
, end
;
int head
, 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: