• [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;
    }
    
  • 相关阅读:
    Wincc的使用
    三菱Ethernet工业以太网
    Wincc flexable的局势视图的组态
    Wincc flexable的数据记录的组态
    Wincc flexable的画面浏览切换组态
    CP342-5做主站的profibus-dp组态应用
    Winccflexable触摸屏的报警
    Wincc flexable的按钮组态
    《Java从入门到精通》第八章学习笔记
    Java Lab(1)控制台下的人物PK
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6792722.html
Copyright © 2020-2023  润新知