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 ; }