LuoguP2633 - Count on a tree

【LuoguP2633】【SP10628】【BZOJ2588】Count on a tree 树上第 K 大
题目链接1: https://www.luogu.org/problemnew/show/P2633
题目链接2: https://www.lydsy.com/JudgeOnline/problem.php?id=2588
题目链接3: https://www.luogu.org/problemnew/show/SP10628
题目链接4: https://www.spoj.com/problems/COT/

前言

本来是打算做 TJOI2018 - 异或 那道题的, 然后又看到这道题, 好像做这道题有助于那道题…然后就开始干

分析

这道题像是组合模板题…用倍增LCA + 主席树, 直接套模板就行了.

有一些需要注意的东西, 边的数组最好开大一点, 不然容易RE, 哪个算法写炸了也容易RE, 所以需要小心谨慎的写代码, 然而Ciyang的倍增写挂了…

主席树我写的指针版, 好像很罕见, 强烈安利, 虽然和数组版没有多大的区别.

对于这道题, 先预处理出LCA, 然后建个树(数组版不需要)

查询时把$ x $和$ y $之间的链提出来, 主席树上存的是前缀和, 那么就需要先求出$ lca(x,y) $

再根据数学上的某些原理(容斥?)求出

$$ Sum(x,y) = sum(x) + sum(y) - sum(lca(x,y)) - sum(lca(x,y)) - sum(f[lca(x,y)])$$

$ f[x] $ 代表 x 的父节点, 然后直接套主席树板子就行了

推荐两个STL必备黑科技, unique 和 lower_bound, 前者那个是给有序数组去重, 后者是有序数组二分查找. 一般都会了, 不会的百度把…

如果出现RE, 找不到原因, 可以去交这道题, 去掉强制在线, 如果WA就是算法问题了.再出现RE可能就是像我一样手残打错了一个数字之类的东西…

代码

评测详情(未开O2): Accepted 100 用时: 1765ms / 内存: 76648KB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
inline int read() {
int e= 0, f= 1;
char ch= getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f= -1;
ch= getchar();
}
while(ch >= '0' && ch <= '9') e= e * 10 + ch - '0', ch= getchar();
return e * f;
}
// READ
int n, m, d, vi[100005], lv[100005], edptr= 1, head[100005], tmpx, tmpy, tmpz;
struct edge {
int to, nexty;
} eds[400001];
// 其实可以 100005 * 2
void add(int a, int b) {
eds[edptr].to= b, eds[edptr].nexty= head[a];
head[a]= edptr++;
return;
}
// edge
struct NODE {
NODE *l, *r;
int v, sum;
} * root[800005];
// 其实可以 100005
NODE *build(int l, int r) {
NODE *nptr= new NODE();
if(l != r) {
int mid= (l + r) >> 1;
nptr->l= build(l, mid), nptr->r= build(mid + 1, r);
}
return nptr;
}
NODE *update(int l, int r, int c, NODE *pre) {
NODE *nptr= new NODE();
nptr->l= pre->l, nptr->r= pre->r, nptr->sum= pre->sum + 1;
if(l != r) {
int mid= (l + r) >> 1;
if(c <= mid)
nptr->l= update(l, mid, c, pre->l);
else
nptr->r= update(mid + 1, r, c, pre->r);
}
return nptr;
}
int query(NODE *ml, NODE *mr, NODE *xl, NODE *xr, int l, int r, int k) {
if(l == r) return l;
int qsum= mr->l->sum + ml->l->sum - xl->l->sum - xr->l->sum;
int mid= (l + r) >> 1;
if(qsum >= k) return query(ml->l, mr->l, xl->l, xr->l, l, mid, k);
return query(ml->r, mr->r, xl->r, xr->r, mid + 1, r, k - qsum);
}
// tree
int deep[100005], f[100005][21];
void dfs(int nown, int fa) {
deep[nown]= deep[fa] + 1;
f[nown][0]= fa;
for(int i= 0; i < 20; i++) f[nown][i + 1]= f[f[nown][i]][i];
// 从0开始...Ciyang写挂了,写成从1开始,然后交了好多遍也没改对
for(int i= head[nown], to; i; i= eds[i].nexty) {
to= eds[i].to;
if(to == fa) continue;
dfs(to, nown);
}
return;
}
void dfs2(int nown) {
root[nown]= update(1, n, lv[nown], root[f[nown][0]]);
for(int i= head[nown], to; i; i= eds[i].nexty) {
to= eds[i].to;
if(to == f[nown][0]) continue;
dfs2(to);
}
return;
}
int lca(int x, int y) {
if(deep[x] < deep[y]) swap(x, y);
for(int i= 19; i > -1; i--) {
if(deep[f[x][i]] >= deep[y]) x= f[x][i];
if(x == y) return x;
}
for(int i= 19; i > -1; i--)
if(f[x][i] != f[y][i]) x= f[x][i], y= f[y][i];
return f[x][0];
}
// LCA
int lastans= 0, tmpc;
int main() {
n= read(), m= read();
for(int i= 1; i <= n; i++) vi[i]= read(), lv[i]= vi[i];
for(int i= 1; i < n; i++) {
tmpx= read(), tmpy= read();
add(tmpx, tmpy), add(tmpy, tmpx);
}
root[0]= build(1, n);
sort(vi + 1, vi + n + 1);
d= unique(vi + 1, vi + n + 1) - vi - 1;
for(int i= 1; i <= n; i++) lv[i]= lower_bound(vi + 1, vi + d + 1, lv[i]) - vi;
dfs(1, 0);
dfs2(1);
while(m--) {
tmpx= read(), tmpy= read(), tmpz= read();
tmpx^= lastans;
tmpc= lca(tmpx, tmpy);
lastans= vi[query(root[tmpx], root[tmpy], root[tmpc], root[f[tmpc][0]], 1, n, tmpz)];
printf("%d\n", lastans);
}
return 0;
}
// main

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×