LuoGuP4197 Peaks
痛苦的心路:
其实这是个码农题?也不算很码农...只要头脑清晰,还是很好写的.
一眼题,学过 \(kruskal\) 重构树的人应该能一眼秒出重构树的做法.
按权值合并,构造重构树,给定起点后在重构树上倍增,因为重构树的点权是自底向上不降的,
所以可以直接倍增去找权值小于等于某个值的深度最浅的点,它的子树中的叶子的点权的第 \(k\) 大就是答案,子树信息用 \(dfs\) 序 \(+\) 主席树即可.
什么,你不会 \(Kruskal\) 重构树?这里不讲,想学去看下一篇.
错因:
读错题了...以为让求第 \(k\) 小,结果调了半天没调出来.
\(Code:\)
#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 ;
}