Fork me on GitHub

LuoGuP4197 Peaks

LuoGuP4197 Peaks

Peaks

痛苦的心路:

cao

其实这是个码农题?也不算很码农…只要头脑清晰,还是很好写的.

一眼题,学过 $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
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#define MEM(x,y) memset ( x , y , sizeof ( x ) )
#define rep(i,a,b) for (int i = (a) ; i <= (b) ; ++ i)
#define per(i,a,b) for (int i = (a) ; i >= (b) ; -- i)
#define pii pair < int , int >
#define one first
#define two second
#define rint read<int>
#define pb push_back
#define db double
#define ull unsigned long long
#define lowbit(x) ( x & ( - x ) )

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 {
#define mid ( ( l + r ) >> 1 )
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 ) ;
}
#undef mid
} 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 ;
}