• _bzoj1036 [ZJOI2008]树的统计Count【树链剖分】


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1036

    保存模版。

    执行qmax与qsum操作,往上爬的时候最开始的代码出了点小问题,往上爬的点应该是dep[top[u]]更深的点,而不是dep[u]更深的点。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    
    const int maxn = 30005;
    
    int n, q, t1, t2, root;
    int head[maxn], to[maxn << 1], next[maxn << 1], lb, cnt;
    int siz[maxn], dep[maxn], fa[maxn], id[maxn], heavy[maxn], v[maxn], top[maxn], a[maxn];
    char opr[10];
    struct Node {
    	int ql, qr, mx, sm;
    } tree[maxn << 2];
    
    inline void ist(int aa, int ss) {
    	to[lb] = ss;
    	next[lb] = head[aa];
    	head[aa] = lb;
    	++lb;
    }
    void dfs1(int r) {
    	siz[r] = 1;
    	dep[r] = dep[fa[r]] + 1;
    	int mx = 0, id = 0;
    	for (int j = head[r]; j != -1; j = next[j]) {
    		if (to[j] != fa[r]) {
    			fa[to[j]] = r;
    			dfs1(to[j]);
    			siz[r] += siz[to[j]];
    			if (siz[to[j]] > mx) {
    				mx = siz[id = to[j]];
    			}
    		}
    	}
    	heavy[r] = id;
    }
    void dfs2(int r, int tp) {
    	if (!r) {
    		return;
    	}
    	top[r] = tp;
    	id[r] = ++cnt;
    	a[cnt] = v[r];
    	dfs2(heavy[r], tp);
    	for (int j = head[r]; j != -1; j = next[j]) {
    		if (to[j] != fa[r] && to[j] != heavy[r]) {
    			dfs2(to[j], to[j]);
    		}
    	}
    }
    void make_tree(int p, int left, int right) {
    	tree[p].ql = left;
    	tree[p].qr = right;
    	if (left == right) {
    		tree[p].mx = tree[p].sm = a[left];
    		return;
    	}
    	int mid = (left + right) >> 1;
    	make_tree(p << 1, left, mid);
    	make_tree(p << 1 | 1, mid + 1, right);
    	tree[p].mx = std::max(tree[p << 1].mx, tree[p << 1 | 1].mx);
    	tree[p].sm = tree[p << 1].sm + tree[p << 1 | 1].sm;
    }
    void upd(int p, int r, int value) {
    	if (tree[p].ql == tree[p].qr) {
    		tree[p].mx = tree[p].sm = value;
    		return;
    	}
    	int mid = (tree[p].ql + tree[p].qr) >> 1;
    	if (r <= mid) {
    		upd(p << 1, r, value);
    	}
    	else {
    		upd(p << 1 | 1, r, value);
    	}
    	tree[p].mx = std::max(tree[p << 1].mx, tree[p << 1 | 1].mx);
    	tree[p].sm = tree[p << 1].sm + tree[p << 1 | 1].sm;
    }
    int getmax(int p, int left, int right) {
    	if (tree[p].ql == left && tree[p].qr == right) {
    		return tree[p].mx;
    	}
    	int mid = (tree[p].ql + tree[p].qr) >> 1;
    	if (right <= mid) {
    		return getmax(p << 1, left, right);
    	}
    	if (left > mid) {
    		return getmax(p << 1 | 1, left, right);
    	}
    	return std::max(getmax(p << 1, left, mid), getmax(p << 1 | 1, mid + 1, right));
    }
    int getsum(int p, int left, int right) {
    	if (tree[p].ql == left && tree[p].qr == right) {
    		return tree[p].sm;
    	}
    	int mid = (tree[p].ql + tree[p].qr) >> 1;
    	if (right <= mid) {
    		return getsum(p << 1, left, right);
    	}
    	if (left > mid) {
    		return getsum(p << 1 | 1, left, right);
    	}
    	return getsum(p << 1, left, mid) + getsum(p << 1 | 1, mid + 1, right);
    }
    int qmax(int u, int v) {
    	int rt = -2147483646;
    	while (top[u] != top[v]) {
    		if (dep[top[u]] < dep[top[v]]) {
    			std::swap(u, v);
    		}
    		rt = std::max(rt, getmax(1, id[top[u]], id[u]));
    		u = fa[top[u]];
    	}
    	if (dep[u] < dep[v]) {
    		std::swap(u, v);
    	}
    	rt = std::max(rt, getmax(1, id[v], id[u]));
    	return rt;
    }
    int qsum(int u, int v) {
    	int rt = 0;
    	while (top[u] != top[v]) {
    		if (dep[top[u]] < dep[top[v]]) {
    			std::swap(u, v);
    		}
    		rt += getsum(1, id[top[u]], id[u]);
    		u = fa[top[u]];
    	}
    	if (dep[u] < dep[v]) {
    		std::swap(u, v);
    	}
    	rt += getsum(1, id[v], id[u]);
    	return rt;
    }
    
    int main(void) {
    	//freopen("in.txt", "r", stdin);
    	unsigned seed;
    	memset(head, -1, sizeof head);
    	memset(next, -1, sizeof next);
    	scanf("%d", &n);
    	seed += n;
    	for (int i = 1; i < n; ++i) {
    		scanf("%d%d", &t1, &t2);
    		ist(t1, t2);
    		ist(t2, t1);
    		seed += t1;
    	}
    	for (int i = 1; i <= n; ++i) {
    		scanf("%d", v + i);
    	}
    	
    	srand(seed);
    	root = rand() % n + 1;
    	dfs1(root);
    	dfs2(root, root);
    	make_tree(1, 1, n);
    	
    	scanf("%d", &q);
    	while (q--) {
    		scanf("%s%d%d", opr, &t1, &t2);
    		if (opr[1] == 'M') {
    			printf("%d
    ", qmax(t1, t2));
    		}
    		else if (opr[1] == 'S') {
    			printf("%d
    ", qsum(t1, t2));
    		}
    		else {
    			upd(1, id[t1], t2);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    第04组 Beta冲刺(2/5)
    第04组 Beta冲刺(1/5)
    第04组 Alpha事后诸葛亮
    第04组 Alpha冲刺(6/6)
    第04组 Alpha冲刺(5/6)
    第04组 Alpha冲刺(4/6)
    第04组 Alpha冲刺(3/6)
    作业2-1:矩阵协方差
    作业lab1-1:lammps教程总结
    如何在服务器上传/下载文件
  • 原文地址:https://www.cnblogs.com/ciao-sora/p/6144767.html
Copyright © 2020-2023  润新知