• BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay


    Description

    在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。

    Input

    第一行三个数N,M,Q。
    第二行N个数,第i个数为h_i
    接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
    接下来Q行,每行三个数v x k,表示一组询问。

    Output

    对于每组询问,输出一个整数表示答案。

    有小于等于 $x$ 这个条件十分不好办 .

    考虑离线,按照 $x$ 从小到大依次加入,查询的时候直接在 $splay$ 中查询第 $k$ 大即可. 

    #include <cstdio>
    #include <algorithm>  
    #include <stack>   
    #define N 600005  
    #define inf 1000000002 
    #define setIO(s) freopen(s".in","r",stdin)  , freopen(s".out","w",stdout)    
    using namespace std;  
    int splay_cnt;      
    namespace IO 
    {   
        char *p1,*p2,buf[100000];
        #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
        int rd() 
        {
            int x=0; 
            char c=nc(); 
            while(c<48) c=nc(); 
            while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); 
            return x;
        }
    }; 
    struct Edge 
    { 
        int u , v , c ;  
    }ed[N]; 
    bool cmp(Edge a, Edge b) 
    {
        return a.c < b.c; 
    }  
    struct Ask 
    { 
        int u , x , k , id ; 
    }as[N]; 
    bool cmp2(Ask a, Ask b) 
    {
        return a.x < b.x;      
    } 
    #define lson ch[x][0] 
    #define rson ch[x][1]  
    stack <int> S; 
    int answer[N], h[N], size[N], f[N], ch[N][2], siz[N], val[N], rt[N], p[N], mk = 0;           
    inline void init(int sz) 
    {
        for(int i = 1; i <= sz ; ++i) S.push(i);   
        for(int i = 1; i <= sz ; ++i) p[i] = i, size[i] = 1; 
    } 
    int find(int x) 
    {
        return p[x] == x ? x : p[x] = find(p[x]); 
    } 
    inline int newnode() 
    {
        int u = S.top();  S.pop(); 
        return u;       
    }
    inline int get(int x) 
    {
        return ch[f[x]][1] == x; 
    }  
    inline void pushup(int x) 
    {
        siz[x] = siz[lson] + siz[rson] + 1;    
    }
    inline void rotate(int x) 
    {
        int old = f[x], fold = f[old], which = get(x); 
        ch[old][which] = ch[x][which ^ 1], f[ch[old][which]] = old;  
        ch[x][which ^ 1] = old, f[old] = x, f[x] = fold; 
        if(fold) ch[fold][ch[fold][1] == old] = x;        
        pushup(old), pushup(x);        
    } 
    inline void splay(int x, int &tar) 
    { 
        int u = f[tar]; 
        for(int fa; (fa = f[x]) ^ u; rotate(x)) 
            if(f[fa] ^ u) 
                rotate(get(fa) == get(x) ? fa : x);   
        tar = x;     
    }
    inline int kth(int x, int k) 
    { 
        if(siz[x] < k) return inf;  
        while(1) 
        {   
            if(k > siz[rson]) 
            {
                k -= (siz[rson] + 1);        
                if(!k) return x;          
                else x = lson;      
            }
            else x = rson;    
        }
    }
    inline void insert(int &x, int ff, int v) 
    {
        if(!x) 
        {
            mk = x = newnode();        
            f[x] = ff, val[x] = v, pushup(x);       
            return; 
        }     
        insert(ch[x][v > val[x]], x, v), pushup(x); 
    }     
    inline void DFS(int y, int x) 
    {       
        if(lson) DFS(y, lson); 
        if(rson) DFS(y, rson);      
        int v = val[x];   
        S.push(x), val[x] = siz[x] = lson = rson = f[x] = 0, insert(rt[y], 0, v), ++splay_cnt;  
        if(splay_cnt % 6 == 0) splay(mk, rt[y]);         
    }   
    inline void connect(int o) 
    {
        int u = ed[o].u, v = ed[o].v;   
        int x = find(u), y = find(v);   
        if(x ^ y) 
        { 
            if(size[y] < size[x]) swap(x, y);    
            p[x] = y, size[y] += size[x], DFS(y, rt[x]);                
        }
    }
    int main() 
    {
        using namespace IO; 
        // setIO("input"); 
        int n, m, q, i, j;   
        n = rd(), m = rd(), q = rd(), init(n);  
        for(i = 1; i <= n ; ++i) h[i] = rd(), insert(rt[i], 0, h[i]);           
        for(i = 1; i <= m ; ++i) ed[i].u = rd(), ed[i].v = rd(), ed[i].c = rd();        
        sort(ed + 1, ed + 1 + m, cmp);      
        for(i = 1; i <= q ; ++i) 
        {
            as[i].u = rd(), as[i].x = rd(), as[i].k = rd(), as[i].id = i; 
        }
        sort(as + 1, as + 1 + q, cmp2);           
        for(i = j = 1; i <= q; ++i) 
        {
            while(ed[j].c <= as[i].x && j <= m) connect(j), ++j; 
            int l = kth(rt[find(as[i].u)], as[i].k);            
            answer[as[i].id] = (l == inf ? inf : val[l]);   
            if(l ^ inf) 
            {
                ++splay_cnt; 
                if(splay_cnt % 6 == 0) splay(l, rt[find(as[i].u)]);
            }      
        }
        for(i = 1; i <= q; ++i) printf("%d
    ",answer[i] == inf ? -1 : answer[i]);  
        return 0; 
    }
    

      

  • 相关阅读:
    [LeetCode]N-Queens
    [LeetCode]Anagrams
    [LeetCode]Permutations II
    [LeetCode]Permutations
    [STL]heap和priority_queue
    [STL]deque和stack、queue
    10、小易记单词--2017网易春招
    29、剑指offer--最小的K个数
    28、剑指offer--数组中出现次数超过一半的数字
    9、涂棋盘--2017网易春招
  • 原文地址:https://www.cnblogs.com/guangheli/p/11330945.html
Copyright © 2020-2023  润新知