标签:端点 tor sort sqrt struct com 输入 tar 输出
[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:
输入
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.
输出
输入示例
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\n", Ans[i]);
return 0;
}
标签:端点 tor sort sqrt struct com 输入 tar 输出
原文地址:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/6792722.html