码迷,mamicode.com
首页 > 其他好文 > 详细

【hiho1065】全图传送

时间:2019-06-08 16:18:54      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:相同   clear   复杂度   tor   dfs   代码   max   upper   cto   

题目大意:给定一棵 N 个节点的树,点有点权,边有边权,给定 M 个询问,每次询问距离 U 节点不超过 R 的点集中,点权最大的点的编号是多少,若有相同点权,取编号较小的点。

题解:
发现是多组询问,而且涉及的问题很难通过子树信息合并来解决。同时距离 U 节点不超过 R 等价于 U 与 V 路径距离不超过 R,可以考虑点分治求解。
先将询问离线。点分治的过程中维护一个 map<> 表示距离当前分治的根节点距离恰好为 R 的最优点的编号,可以通过在分治过程中遍历一遍子树求得,时间复杂度为 \(O(nlogn)\),再利用维护得 map 进行构造出距离当前分治中心距离不超过 R 的最优解,即:利用 map 的前一项更新后一项即可。处理出这个之后,再进行遍历子树的操作,对于遍历到的每个点进行查询并更新答案即可。总时间复杂度为 \(O(nlog^2n)\)

代码如下

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int maxn=1e5+10;
typedef long long LL;
typedef pair<int,int> P;

int n,m,val[maxn],ans[maxn];
vector<P> q[maxn]; // [r, id]
struct node{int nxt,to;LL w;}e[maxn<<1];
int tot=1,head[maxn];
inline void add_edge(int from,int to,LL w){
    e[++tot]=node{head[from],to,w},head[from]=tot;
}
int rt,sn,sz[maxn],f[maxn];
LL d[maxn];
map<LL,int> rec;
bool vis[maxn];
void getrt(int u,int fa){
    sz[u]=1,f[u]=0;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa||vis[v])continue;
        getrt(v,u);
        f[u]=max(f[u],sz[v]);
        sz[u]+=sz[v];
    }
    f[u]=max(f[u],sn-sz[u]);
    if(!rt||f[u]<f[rt])rt=u;
}

int better(int x,int y){
    return val[x]>val[y]||(val[x]==val[y]&&x<y)?x:y;
}
void getdis(int u,int fa,LL dist){
    auto it=rec.find(dist);
    if(it==rec.end())rec[dist]=u;
    else rec[dist]=better(rec[dist],u);
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to; LL w=e[i].w;
        if(v==fa||vis[v])continue;
        getdis(v,u,dist+w);
    }
}
void update(int u,int fa,LL dist){
    for(auto p:q[u]){
        LL r=p.fi; int id=p.se;
        auto it=rec.upper_bound(r-dist);
        if(it!=rec.begin()){
            --it;
            if(!ans[id])ans[id]=it->se;
            else ans[id]=better(ans[id],it->se);
        }
    }
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to; LL w=e[i].w;
        if(v==fa||vis[v])continue;
        update(v,u,dist+w);
    }
} 
void dfs(int u){
    vis[u]=1;
    
    rec.clear();
    getdis(u,0,0);
    for(auto x=rec.begin();;x++){
        auto y=x; ++y;
        if(y==rec.end())break;
        y->se=better(x->se,y->se);
    }
    update(u,0,0);
    
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(vis[v])continue;
        sn=sz[v],rt=0;
        getrt(v,0);
        dfs(rt);
    }
}

void read_and_parse(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&val[i]);
    for(int i=1;i<n;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add_edge(x,y,z),add_edge(y,x,z);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        int u,r;
        scanf("%d%d",&u,&r);
        q[u].pb(mp(r,i));
    }
}
void solve(){
    sn=n,getrt(1,0);
    dfs(rt);
    for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}
int main(){
    read_and_parse();
    solve();
    return 0;
}

【hiho1065】全图传送

标签:相同   clear   复杂度   tor   dfs   代码   max   upper   cto   

原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10990941.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!