码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces 191C Fools and Roads 树上的前缀和 LCA

时间:2015-02-07 21:41:38      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:点击打开链接

题意:

给定n个点的树。

下面m个操作,每次给一条路径上的边都染一次。

最后问:每个边被染色的次数。

和去年网赛的一道差不多,就是类似前缀和的做法,

我们在某个点+1然后从叶子节点到根节点求一个前缀和,这样某个点加1就相当于某个点到根的路径都加了1.

所以当我们给[u,v]染色时就 sum[u]++; sum[v]++; sum[LCA(u,v)]-=2;

再把重复的部分减掉即可。

最后求个前缀和。

#include <cstdio>
#include <vector>
#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <cstring>
#include <cmath>
#include <string>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int inf = 1e9;
const int mod = 1e9+7;
const int N = 5*100001;
const int M = 20050;
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x <0) {
		putchar('-');
		x *= -1;
	}
	if (x>9) pt(x / 10);
	putchar(x % 10 + '0');
}
struct Edge{
	int from, to, nex, id;
	Edge(int f = 0, int t = 0, int n = 0, int i = 0) :from(f), to(t), nex(n), id(i){}
}edge[N << 1];
int head[N], edgenum;
void add(int u, int v, int id){
	Edge E = { u, v, head[u], id };
	edge[edgenum] = E;
	head[u] = edgenum++;
}
int fa[N][20], dep[N], dis[N], edge_id[N];
void bfs(int root){
	queue<int> q;
	fa[root][0] = root; dep[root] = 0; dis[root] = 0;
	q.push(root);
	while (!q.empty()){
		int u = q.front(); q.pop();
		for (int i = 1; i<20; i++)fa[u][i] = fa[fa[u][i - 1]][i - 1];
		for (int i = head[u]; ~i; i = edge[i].nex){
			int v = edge[i].to;
			if (v == fa[u][0])continue;	
			edge_id[edge[i].id] = v;		
			dep[v] = dep[u] + 1; dis[v] = dis[u] + 1; fa[v][0] = u;
			q.push(v);
		}
	}
}
int Lca(int x, int y){
	if (dep[x]<dep[y])swap(x, y);
	for (int i = 0; i<20; i++)if ((dep[x] - dep[y])&(1 << i))x = fa[x][i];
	if (x == y)return x;
	for (int i = 19; i >= 0; i--)if (fa[x][i] != fa[y][i])x = fa[x][i], y = fa[y][i];
	return fa[x][0];
}
int n, q;
void input(){
	rd(n);
	memset(head, -1, sizeof head); edgenum = 0;
	for (int i = 1, u, v; i < n; i++){
		rd(u); rd(v); add(u, v, i); add(v, u, i);
	}
	rd(q);
}
int ans[N], val[N];
void put(){
	for (int i = 1; i < n; i++)printf("%d ", val[edge_id[i]]); puts("");
}
void dfs(int u, int fa){
	for (int i = head[u]; ~i; i = edge[i].nex){
		int v = edge[i].to; if (v == fa)continue;
		dfs(v, u);
		val[u] += val[v];
	}
}
int main() {
	input();
	bfs(1);
	memset(val, 0, sizeof val);
	while (q--){
		int u, v; rd(u); rd(v);
		val[u]++; val[v]++;
		val[ Lca(u, v) ] -= 2;
	}
	dfs(1, 1);
	put();
	return 0;
}
/*
14
1 2
1 3
1 4
2 13
13 14
3 10
10 12
10 11
4 5
5 9
5 8
6 4
6 7
13
1 7
1 14
1 12
1 11
1 9
1 8
5 12
7 11
14 8
9 3
6 10
4 14
3 10
12 13



*/


CodeForces 191C Fools and Roads 树上的前缀和 LCA

标签:

原文地址:http://blog.csdn.net/qq574857122/article/details/43610785

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!