• [牛客练习赛61F]苹果树——点分树,动态开点线段树


    苹果树

           把点分治的过程所有重心连成一颗树,那么这颗树高为logn。预处理重建树上每个节点到所有子节点的距离(原树上的距离)。对于每次查询和修改,在重建树上不断往上跳,每个节点开一个动态开点的线段树,进行查询。由于树高是logn的,所以时间复杂度为nlognlogn。空间复杂度也为nlognlogn。两点间距离可以用map存,可以用lca,也可以存每个节点到第i层的父节点的距离。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+10;
    const int M=1e5+10;
    const int maxn=1e7;
    const int INF=0x3f3f3f3f;
    int head[N],ver[2*M],edge[2*M],nex[2*M],tot=1;
    inline void add(int x,int y,int z) {
        ver[++tot]=y,edge[tot]=z,nex[tot]=head[x],head[x]=tot;
    }
    
    int lc[maxn],rc[maxn],Min[maxn],cnt=0,rt[N];//rt:线段树根
    void insert(int &o,int pos,int v,int l,int r){
        if(o==0)Min[o=++cnt]=INF;
        if(l==r){Min[o]=min(Min[o],v);return;}
        int m=(l+r)>>1;
        if(pos<=m)insert(lc[o],pos,v,l,m);
        else insert(rc[o],pos,v,m+1,r);
        Min[o]=min(Min[lc[o]],Min[rc[o]]);
    }
    int query(int o,int a,int b,int l,int r){
        if(o==0)return INF;
        if(a<=l&&b>=r)return Min[o];
        int m=(l+r)>>1,res=INF;
        if(a<=m)res=query(lc[o],a,b,l,m);
        if(b>m)res=min(res,query(rc[o],a,b,m+1,r));
        return res;
    }
    
    int vis[N],sz[N],sub_sz,max_sz,root;
    void get_root(int x,int fa){
        int max_part=0;sz[x]=1;
        for(int i=head[x];i;i=nex[i]){
            int y=ver[i];if(y==fa||vis[y])continue;
            get_root(y,x);sz[x]+=sz[y];
            max_part=max(max_part,sz[y]);
        }
        max_part=max(max_part,sub_sz-sz[x]);
        if(max_part<max_sz){max_sz=max_part;root=x;}
    }
    int v[N],fa[N],dep[N],dis[N][20];
    void get_dis(int x,int fa,int d){
        dis[x][dep[root]]=d;//这里root刚好是重心
        insert(rt[root],v[x],d,1,N);
        for(int i=head[x];i;i=nex[i]){
            int y=ver[i];if(y==fa||vis[y])continue;
            get_dis(y,x,d+edge[i]);
        }
    }
    void divide(int x,int depth){
        vis[x]=1;
        dep[x]=depth;
        get_dis(x,0,0);
        int tot_sz=sub_sz;//当前处理的树的大小
        for(int i=head[x]; i; i=nex[i]) {
            int y=ver[i];if(vis[y])continue;
            max_sz=INF;
            sub_sz=sz[y]>sz[x]?tot_sz-sz[x]:sz[y];//获取子树大小
            get_root(y,0);
            fa[root]=x;
            divide(root,depth+1);
        }
    }
    
    int main(){
        int n,m,op,u,x,y,z;
        Min[0]=INF;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)scanf("%d",v+i);
        for(int i=1;i<n;++i){
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);add(y,x,z);
        }
        sub_sz=n;max_sz=INF;
        get_root(1,0);
        divide(root,0);
        while(m--){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d",&x,&y);z=x;
                while(z)insert(rt[z],y,dis[x][dep[z]],1,N),z=fa[z];
            }else{
                scanf("%d%d%d",&u,&x,&y);
                int ans=INF;z=u;
                while(z)ans=min(ans,dis[u][dep[z]]+query(rt[z],x,y,1,N)),z=fa[z];
                if(ans==INF)puts("-1");
                else printf("%d
    ",2*ans);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    访问静态文件时, 为NetCore项目添加MIME类型支持
    Ant design pro formItem validator报警告 `callback` is deprecated. Please return a promise instead.
    .NET Core 自定义过滤器 AllowAnonymous 失效问题
    前端获取二进制流下载文件并解决无法获header问题,Content-Disposition
    cefSharp通过js操控页面,含跨域操控
    C#中Application.StartupPath和System.Environment.CurrentDirectory的区别
    C# XML配置文件读写类(用于程序配置保存)
    C#爬虫使用代理刷文章浏览量
    c#批量抓取免费代理并验证有效性
    C# 代理HTTP请求
  • 原文地址:https://www.cnblogs.com/zpengst/p/12704161.html
Copyright © 2020-2023  润新知