树链剖分刷水

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 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[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 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[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;
}


阅读更多
版权声明:转载请注明 http://blog.csdn.net/huanghongxun/ https://blog.csdn.net/huanghongxun/article/details/49963287
文章标签: bzoj
个人分类: 树剖LCT
想对作者说点什么? 我来说一句

SAI水墨笔刷

2014年06月03日 574B 下载

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

2014年02月10日 4.33MB 下载

7种水溅水花水浪笔刷

2015年04月12日 784KB 下载

树链剖分

2015年09月22日 800KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭