zoukankan      html  css  js  c++  java
  • [SPOJ10707]Count on a tree II

    [SPOJ10707]Count on a tree II

    试题描述

    You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer weight.

    We will ask you to perform the following operation:

    • u v : ask for how many different integers that represent the weight of nodes there are on the path from u to v.

    输入

    In the first line there are two integers N and M. (N <= 40000, M <= 100000)

    In the second line there are N integers. The i-th integer denotes the weight of the i-th node.

    In the next N-1 lines, each line contains two integers u v, which describes an edge (u, v).

    In the next M lines, each line contains two integers u v, which means an operation asking for how many different integers that represent the weight of nodes there are on the path from u to v.

    输出

    For each operation, print its result.

    输入示例

    8 2
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5
    7 8

    输出示例

    4
    4

    数据规模及约定

    见“输入

    题解

    树上莫队。

    就是树上分块(见上一题);接着对询问路径按照左端点所在块为第一关键字,右端点 dfs 序为第二关键字(随便让哪个点作为左端点都无所谓);然后暴力从一条路径 (a, b) 更新到另一条路径 (a', b')。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 50010
    #define maxm 100010
    #define maxq 100010
    #define maxlog 17
    
    int n, m, head[maxn], nxt[maxm], to[maxm], col[maxn], num[maxn];
    
    void AddEdge(int a, int b) {
    	to[++m] = b; nxt[m] = head[a]; head[a] = m;
    	swap(a, b);
    	to[++m] = b; nxt[m] = head[a]; head[a] = m;
    	return ;
    }
    
    int fa[maxn], dep[maxn], mnp[maxlog][maxn<<1], dfn[maxn], clo, Bsiz, blid[maxn], cb, S[maxn], top;
    void build(int u) {
    	dfn[u] = ++clo; mnp[0][clo] = u;
    	int bot = top;
    	for(int e = head[u]; e; e = nxt[e]) if(to[e] != fa[u]) {
    		fa[to[e]] = u; dep[to[e]] = dep[u] + 1;
    		build(to[e]); mnp[0][++clo] = u;
    		if(top - bot >= Bsiz) {
    			cb++;
    			while(top > bot) blid[S[top--]] = cb;
    		}
    	}
    	S[++top] = u;
    	return ;
    }
    int Log[maxn<<1];
    void rmq_init() {
    	Log[1] = 0;
    	for(int i = 2; i <= clo; i++) Log[i] = Log[i>>1] + 1;
    	for(int j = 1; (1 << j) <= clo; j++)
    		for(int i = 1; i + (1 << j) - 1 <= clo; i++) {
    			int a = mnp[j-1][i], b = mnp[j-1][i+(1<<j-1)];
    			mnp[j][i] = dep[a] < dep[b] ? a : b;
    		}
    	return ;
    }
    int lca(int a, int b) {
    	int l = dfn[a], r = dfn[b];
    	if(l > r) swap(l, r);
    	int t = Log[r-l+1];
    	a = mnp[t][l]; b = mnp[t][r-(1<<t)+1];
    	return dep[a] < dep[b] ? a : b;
    }
    
    int q;
    struct Que {
    	int u, v, id;
    	Que() {}
    	Que(int _1, int _2, int _3): u(_1), v(_2), id(_3) {}
    	bool operator < (const Que& t) const { return blid[u] != blid[t.u] ? blid[u] < blid[t.u] : dfn[v] < dfn[t.v]; }
    } qs[maxq];
    
    int U, V, ans, tot[maxn], Ans[maxq];
    bool tag[maxn];
    void rev(int u) {
    	if(tag[u]) {
    		if(!--tot[col[u]]) ans--;
    	}
    	else {
    		if(++tot[col[u]] == 1) ans++;
    	}
    	tag[u] ^= 1;
    	return ;
    }
    void change(int& node, int tar) {
    	int c = lca(node, tar), c2 = lca(U, V);
    	bool has = 0;
    	while(node != c) rev(node), node = fa[node];
    	int ttar = tar;
    	while(tar != c) rev(tar), tar = fa[tar];
    	rev(c);
    	node = ttar;
    	int c3 = lca(U, V);
    	if(dep[c] < dep[c2]) c = c2;
    	if(dep[c] < dep[c3]) c = c3;
    	rev(c);
    	return ;
    }
    
    int main() {
    	n = read(); q = read();
    	for(int i = 1; i <= n; i++) num[i] = col[i] = read();
    	sort(num + 1, num + n + 1);
    	for(int i = 1; i <= n; i++) col[i] = lower_bound(num + 1, num + n + 1, col[i]) - num;
    	for(int i = 1; i < n; i++) {
    		int a = read(), b = read();
    		AddEdge(a, b);
    	}
    	Bsiz = sqrt(n + .5);
    	build(1);
    	while(top) blid[S[top--]] = cb;
    	rmq_init();
    	
    	for(int i = 1; i <= q; i++) {
    		int a = read(), b = read();
    		qs[i] = Que(a, b, i);
    	}
    	sort(qs + 1, qs + q + 1);
    	
    	U = V = ans = tot[col[1]] = tag[1] = 1;
    	for(int i = 1; i <= q; i++) {
    		change(U, qs[i].u);
    		change(V, qs[i].v);
    		Ans[qs[i].id] = ans;
    	}
    	for(int i = 1; i <= q; i++) printf("%d
    ", Ans[i]);
    	
    	return 0;
    }
    
  • 相关阅读:
    HDU 5791 Two (DP)
    POJ 1088 滑雪 (DPor记忆化搜索)
    LightOJ 1011
    POJ 1787 Charlie's Change (多重背包 带结果组成)
    HDU 5550 Game Rooms (ccpc2015 K)(dp)
    HDU 5542 The Battle of Chibi (ccpc 南阳 C)(DP 树状数组 离散化)
    HDU 5543 Pick The Sticks (01背包)
    HDU 5546 Ancient Go (ccpc2015南阳G)
    NB-IoT的DRX、eDRX、PSM三个模式 (转载,描述的简单易懂)
    MQTT 嵌入式端通讯协议解析(转)
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6792722.html
Copyright © 2011-2022 走看看