zoukankan      html  css  js  c++  java
  • HDU4366 Successor【dfs序 分块】

    HDU4366 Successor

    题意:

    给出一棵根为(1)的树,每个点有两个权值(x,y),每次询问一个点的子树中(x)比这个点的(x)大且(y)值最大的那个点

    题解:

    如果以dfs序来看的话,每个点的子树可以看作是dfs序的一段区间
    然后我们对这个序列分块,每个块内按(x)排序,然后维护后缀(y)的最大值
    每次查询的时候对于一个块,可以先二分出来符合条件的(x)最小的那个位置,然后找后缀(y)最大的那个点

    如果要单点修改的话,每次对一个块暴力修改也是没有问题的

    
    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 5e4+7;
    int T,n,m,q;
    vector<int> G[MAXN];
    int st[MAXN],ed[MAXN],belong[MAXN],l[MAXN],r[MAXN],sqt;
    pair<int,int> emp[MAXN];
    vector<int> ord;
    void dfs(int u){
        st[u] = ord.size();
        ord.push_back(u);
        for(int v : G[u]) dfs(v);
        ed[u] = ord.size() - 1;
    }
    void divide(){
        sqt = sqrt(n);
        m = n / sqt + (n%sqt==0?0:1);
        for(int i = 0; i < n; i++) belong[i] = i / sqt + 1;
        for(int i = 1; i <= m; i++) l[i] = sqt * (i-1), r[i] = sqt * i - 1;
        r[m] = n - 1;
    }
    vector<pair<pair<int,int>,int>> vec[MAXN];
    vector<pair<int,int>> suf[MAXN];
    void build(){
        for(int i = 1; i <= m; i++){
            vec[i].clear(); suf[i].clear();
            for(int j = l[i]; j <= r[i]; j++) vec[i].emplace_back(make_pair(emp[ord[j]],ord[j]));
            sort(vec[i].begin(),vec[i].end());
            suf[i].resize(vec[i].size());
            suf[i].back() = make_pair(vec[i].back().first.second,vec[i].back().second);
            for(int j = ((int)suf[i].size()) - 2; j >= 0; j--){
                if(vec[i][j].first.second>suf[i][j+1].first) suf[i][j] = make_pair(vec[i][j].first.second,vec[i][j].second);
                else suf[i][j] = suf[i][j+1];
            }
        }
    }
    void ask(){
        int x;
        scanf("%d",&x); x++;
        int L = st[x], R = ed[x];
        x = emp[x].first;
        int lp = belong[L], rp = belong[R];
        int res = -1;
        if(lp==rp){
            for(int i = L; i <= R; i++){
                if(emp[ord[i]].first<=x) continue;
                if(res==-1) res = ord[i];
                else if(emp[ord[i]].second>emp[res].second) res = ord[i];
            }
        }
        else{
            for(int i = L; i <= r[lp]; i++){
                if(emp[ord[i]].first<=x) continue;
                if(res==-1) res = ord[i];
                else if(emp[ord[i]].second>emp[res].second) res = ord[i];
            }
            for(int i = l[rp]; i <= R; i++){
                if(emp[ord[i]].first<=x) continue;
                if(res==-1) res = ord[i];
                else if(emp[ord[i]].second>emp[res].second) res = ord[i];
            }
            lp++, rp--;
            for(int i = lp; i <= rp; i++){
                auto p = lower_bound(vec[i].begin(),vec[i].end(),make_pair(make_pair(x+1,0),1));
                if(p==vec[i].end()) continue;
                int pt = p - vec[i].begin();
                if(res==-1 or suf[i][pt].first>emp[res].second) res = suf[i][pt].second;
            }
        }
        printf("%d
    ",res==-1?-1:res-1);
    }
    void solve(){
        scanf("%d %d",&n,&q);
        for(int i = 1; i <= n; i++) G[i].clear();
        for(int i = 2; i <= n; i++){
            int x;
            scanf("%d %d %d",&x,&emp[i].second,&emp[i].first);
            G[++x].push_back(i);
        }
        ord.clear();
        dfs(1);
        divide();
        build();
        while(q--) ask();
    }
    int main(){
        for(scanf("%d",&T); T; T--) solve();
        return 0;
    }
    
  • 相关阅读:
    OSG开源教程(转)
    小组项目工作分配,任务确认
    OSG安装编译
    JAVA开发工具IDEA使用体验
    软件工程结对项目总结
    迭代开发个人总结20160705
    迭代开发个人总结20160704
    迭代开发个人总结20160703
    迭代开发个人总结20160702
    迭代开发个人总结20160701
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12890019.html
Copyright © 2011-2022 走看看