zoukankan      html  css  js  c++  java
  • 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
    ", num[ans[i]]);
    	return 0;
    }
    
  • 相关阅读:
    mac使用vnc远程登录ubuntu16.04桌面
    last的用法
    MAC笔记本安装telnet
    lsyncd自动同步配置
    四则运算——安卓版
    敏捷开发方法综述
    数组2——数组首尾相接,求最大子数组
    数组1——求一个数组的最大子数组
    《构建之法》阅读笔记04
    学习进度条——第四周
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8464132.html
Copyright © 2011-2022 走看看