LuoGuP4197 Peaks

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 ;
}
01-20 07:28