LuoGuP4197 Peaks
痛苦的心路:
其实这是个码农题?也不算很码农…只要头脑清晰,还是很好写的.
一眼题,学过 $kruskal$ 重构树的人应该能一眼秒出重构树的做法.
按权值合并,构造重构树,给定起点后在重构树上倍增,因为重构树的点权是自底向上不降的,
所以可以直接倍增去找权值小于等于某个值的深度最浅的点,它的子树中的叶子的点权的第 $k$ 大就是答案,子树信息用 $dfs$ 序 $+$ 主席树即可.
什么,你不会 $Kruskal$ 重构树?这里不讲,想学去看下一篇.
错因:
读错题了…以为让求第 $k$ 小,结果调了半天没调出来.
$Code:$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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using std::queue ;
using std::set ;
using std::pair ;
using std::max ;
using std::min ;
using std::priority_queue ;
using std::vector ;
using std::swap ;
using std::sort ;
using std::unique ;
using std::greater ;
template < class T >
inline T read () {
T x = 0 , f = 1 ; char ch = getchar () ;
while ( ch < '0' || ch > '9' ) {
if ( ch == '-' ) f = - 1 ;
ch = getchar () ;
}
while ( ch >= '0' && ch <= '9' ) {
x = ( x << 3 ) + ( x << 1 ) + ( ch - 48 ) ;
ch = getchar () ;
}
return f * x ;
}
const int N = 1e5 + 100 ;
const int M = 5e5 + 100 ;
const int inf = 1e15 ;
struct edge {
int to , from , data ;
inline bool operator < (const edge & a) { return data < a.data ; }
} e[M] ;
class Chairman {
private :
struct Tree { int ls , rs , data ; } t[N*40] ;
public :
int rt[N<<1] ;
private :
int crt ;
public :
inline void initial () { crt = 0 ; return ; }
private :
inline void pushup (int rt) { t[rt].data = t[t[rt].ls].data + t[t[rt].rs].data ; return ; }
public :
inline void insert (int & rt , int l , int r , int key) {
t[++crt] = t[rt] ; rt = crt ;
if ( l == r ) { ++ t[rt].data ; return ; }
if ( key <= mid ) insert ( t[rt].ls , l , mid , key ) ;
else insert ( t[rt].rs , mid + 1 , r , key ) ;
pushup ( rt ) ; return ;
}
public:
inline int query (int u , int v , int l , int r , int key) {
if ( l == r ) return l ;
int T = t[t[v].ls].data - t[t[u].ls].data ;
if ( key <= T ) return query ( t[u].ls , t[v].ls , l , mid , key ) ;
else return query ( t[u].rs , t[v].rs , mid + 1 , r , key - T ) ;
}
} T ;
vector < int > G[N<<1] ;
int n , m , g[N<<1] , cnt , tot , siz[N<<1] ;
int v[N<<1] , f[25][N<<1] , deep[N<<1] , idx[N<<1] ;
int val[N<<1] , ndx , wt[N<<1] , h[N<<1] , q ;
inline void build (int u , int v , int w) {
e[++tot].from = u ; e[tot].to = v ;
e[tot].data = w ; return ;
}
inline int getf (int x) { return g[x] == x ? x : g[x] = getf ( g[x] ) ; }
inline void Kruskal () {
sort ( e + 1 , e + tot + 1 ) ; cnt = n ;
rep ( i , 1 , n << 1 ) g[i] = i ; int num = 0 ;
rep ( i , 1 , tot ) {
int x = getf ( e[i].from ) , y = getf ( e[i].to ) ;
if ( x != y ) {
++ cnt ; v[cnt] = e[i].data ;
g[x] = g[y] = g[cnt] = cnt ;
G[cnt].pb ( x ) ; G[cnt].pb ( y ) ;
}
}
return ;
}
inline void dfs (int cur , int anc , int dep) {
f[0][cur] = anc ; deep[cur] = dep ; siz[cur] = 1 ;
idx[cur] = ++ ndx ; val[ndx] = h[cur] ;
for (int i = 1 ; ( 1 << i ) <= dep ; ++ i)
f[i][cur] = f[i-1][f[i-1][cur]] ;
for (int k : G[cur] ) {
if ( k == anc ) continue ;
dfs ( k , cur , dep + 1 ) ;
siz[cur] += siz[k] ;
}
return ;
}
inline int getp (int x , int key) {
int k = log2 ( deep[x] ) + 1 ;
for (int i = k ; i >= 0 ; -- i)
if ( v[f[i][x]] <= key && f[i][x] != 0 )
x = f[i][x] ;
return x ;
}
signed main (int argc , char * argv[]) {
n = rint () ; m = rint () ; q = rint () ;
rep ( i , 1 , n << 1 ) h[i] = - inf ; rep ( i , 1 , n ) h[i] = rint () ;
rep ( i , 1 , m ) { int u = rint () , v = rint () , w = rint () ; build ( u , v , w ) ; }
Kruskal () ; dfs ( cnt , 0 , 1 ) ;
T.initial () ; rep ( i , 1 , ndx ) wt[i] = val[i] ;
sort ( wt + 1 , wt + ndx + 1 ) ; wt[0] = unique ( wt + 1 , wt + ndx + 1 ) - wt - 1 ;
rep ( i , 1 , ndx ) val[i] = std::lower_bound ( wt + 1 , wt + wt[0] + 1 , val[i] ) - wt ;
T.rt[0] = 0 ; rep ( i , 1 , ndx ) { T.rt[i] = T.rt[i-1] ; T.insert ( T.rt[i] , 1 , wt[0] , val[i] ) ; }
while ( q -- ) {
int p = rint () , x = rint () , k = rint () ;
int root = getp ( p , x ) ;
int l = idx[root] , r = idx[root] + siz[root] - 1 ;
int pos = T.query ( T.rt[l-1] , T.rt[r] , 1 , wt[0] , r - l + 1 - k + 1 ) ;
if ( wt[pos] != - inf ) printf ("%lld\n" , wt[pos] , pos ) ;
else puts ("-1") ;
}
system ("pause") ; return 0 ;
}