BZOJ3307: 雨天的尾巴

3307: 雨天的尾巴

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 843 Solved: 345
[Submit][Status][Discuss]

Description

N个点,形成一个树状结构。有M次发放,每次选择两个点x,y
对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成
所有发放后,每个点存放最多的是哪种物品。

Input

第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题

Output

输出有N行
每i行的数字表示第i个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0

Sample Input

20 50

8 6

10 6

18 6

20 10

7 20

2 18

19 8

1 6

14 20

16 10

13 19

3 14

17 18

11 19

4 11

15 14

5 18

9 10

12 15

11 14 87

12 1 87

14 3 84

17 2 36

6 5 93

17 6 87

10 14 93

5 16 78

6 15 93

15 5 16

11 8 50

17 19 50

5 4 87

15 20 78

1 17 50

20 13 87

7 15 22

16 11 94

19 8 87

18 3 93

13 13 87

2 1 87

2 6 22

5 20 84

10 12 93

18 12 87

16 10 93

8 17 93

14 7 36

7 4 22

5 9 87

13 10 16

20 11 50

9 16 84

10 17 16

19 6 87

12 2 36

20 9 94

9 2 84

14 1 94

5 5 94

8 17 16

12 8 36

20 17 78

12 18 50

16 8 94

2 19 36

10 18 36

14 19 50

4 12 50

Sample Output

87

36

84

22

87

87

22

50

84

87

50

36

87

93

36

94

16

87

50

50

HINT

1<=N,M<=100000

1<=a,b,x,y<=N

1<=z<=10^9

题解

空间卡很紧,因为空间开小了WA了三发,跟管理员要了数据才调A的。。
离线询问,在每个节点维护一颗权值线段树,对于每个修改操作(u,v),把u这个位置+1,v+1,lca(u,v)-1,fa(lca(u,v))-1,按照倒序dfs访问,每个节点把当前节点和他的儿子的sgt合并起来。
他们说这是很常用的手段。。Orz
http://blog.csdn.net/ww140142/article/details/48660513
这里有很好的复杂度分析。。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(x) ((x) < 0 ? -1 * (x) : (x))
template <class T>
inline void swap(T &x, T &y)
{
	T tmp = x;x = y, y = tmp;
} 
template <class T>
inline void read(T &x)
{
	x = 0;char ch = getchar(), c = ch;
	while(ch < '0' || ch > '9') c = ch, ch = getchar();
	while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
	if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = 100000 + 10;

int n, q, ans[MAXN];

//离散化
int u[MAXN], v[MAXN], w2[MAXN], w1[MAXN], cnt[MAXN], tt, num[MAXN];
bool cmp(int a, int b)
{
	return w1[a] < w1[b];
}

//LCA 
struct Edge
{
	int v,nxt;
	Edge(int _v, int _nxt){v = _v;nxt = _nxt;}
	Edge(){}
}edge[MAXN << 1];
int head[MAXN], cntt, tag[MAXN], p[MAXN][25], deep[MAXN], pos[MAXN], dfn[MAXN], t, M;
inline void insert(int a, int b)
{
	edge[++cntt] = Edge(b,head[a]);
	head[a] = cntt;
}
void dfs(int x)
{
	dfn[x] = ++ t;pos[t] = x;
	for(int pos = head[x];pos;pos = edge[pos].nxt)
	{
		int v = edge[pos].v;
		if(p[x][0] == v) continue;
		p[v][0] = x, deep[v] = deep[x] + 1, dfs(v);
	}
}
void yuchuli()
{
	for(int i = 1;i <= n;++ i) if(!dfn[i]) dfs(i);
	M = 0;
	while((1 << M) <= n) ++ M; -- M;
	for(int i = 1;i <= M;++ i)
		for(int j = 1;j <= n;++ j)
			p[j][i] = p[p[j][i - 1]][i - 1];
}
int LCA(int x, int y)
{
	if(deep[x] < deep[y]) swap(x, y);
	for(int i = M;i >= 0;-- i)
		if(deep[x] - deep[y] >= (1 << i))
			x = p[x][i];
	if(x == y) return x;
	for(int i = M;i >= 0;-- i)
		if(p[x][i] != p[y][i])
			x = p[x][i], y = p[y][i];
	return p[x][0];
}

//SGT
struct Node
{
	int data, p, ls, rs;
}node[MAXN * 50];
int stack[MAXN * 50], top, tot, root[MAXN];
inline int newnode()
{
	return top ? stack[top --] : ++ tot;
}
inline void delnode(int x)
{
	node[x].data = node[x].ls = node[x].rs = node[x].p = 0;
	stack[++ top] = x;
}
inline void pushup(int o)
{
	int ls = node[o].ls, rs = node[o].rs;
	if(node[ls].data >= node[rs].data) node[o].data = node[ls].data, node[o].p = node[ls].p;
	else node[o].data = node[rs].data, node[o].p = node[rs].p;
	if(node[o].data == 0) node[o].p = 0;
	return;
}
int merge(int x, int y, int l = 1, int r = tt)
{
	if(!x) return y;
	if(!y) return x;
	int mid = (l + r) >> 1;
	int tmp = newnode();
	if(l == r)
	{
		node[tmp].data = node[x].data + node[y].data;
		node[tmp].p = l;
	}
	else
	{
		node[tmp].ls = merge(node[x].ls, node[y].ls, l, mid); 
		node[tmp].rs = merge(node[x].rs, node[y].rs, mid + 1, r);
		pushup(tmp);
	}
	delnode(x), delnode(y);
	if(node[tmp].data == 0) node[tmp].p = 0;
	return tmp;
}
void modify(int p, int k, int &o, int l = 1, int r = tt)
{
	if(!o) o = newnode();
	if(l == r && l == p)
	{
		node[o].data += k, node[o].p = l;
		return;
	}
	int mid = (l + r) >> 1;
	if(p <= mid) modify(p, k, node[o].ls, l, mid);
	else modify(p, k, node[o].rs, mid + 1, r);
	pushup(o);
}
int main()
{
	read(n), read(q);
	for(int i = 1;i < n;++ i)
	{
		int tmp1, tmp2;
		read(tmp1), read(tmp2);
		insert(tmp1, tmp2), insert(tmp2, tmp1); 
	}
	yuchuli();
	for(int i = 1;i <= q;++ i)
		read(u[i]), read(v[i]), read(w1[i]), cnt[i] = i;
	std::sort(cnt + 1, cnt + 1 + q, cmp);
	num[++ tt] = w1[cnt[1]], w2[cnt[1]] = tt;
	for(int i = 1;i < q;++ i)
		if(w1[cnt[i]] != w1[cnt[i + 1]]) num[++ tt] = w1[cnt[i + 1]] , w2[cnt[i + 1]] = tt;
		else w2[cnt[i + 1]] = tt;
	for(int i = 1;i <= q;++ i)
	{
		int lca = LCA(u[i], v[i]);
		modify(w2[i], 1, root[u[i]]);
		modify(w2[i], 1, root[v[i]]);
		modify(w2[i], -1, root[lca]);
		if(p[lca][0]) modify(w2[i], -1, root[p[lca][0]]);
	}
	for(int j = n;j >= 1;-- j)
	{
		int i = pos[j];
		for(int pos = head[i];pos;pos = edge[pos].nxt)
		{
			int v = edge[pos].v;
			if(v == p[i][0]) continue;
			root[i] = merge(root[i], root[v]);
		}
		ans[i] = node[root[i]].p;
	}
	for(int i = 1;i <= n;++ i) printf("%d\n", num[ans[i]]);
	return 0;
}
posted @ 2018-02-24 09:35  嘒彼小星  阅读(243)  评论(0编辑  收藏  举报