zoukankan      html  css  js  c++  java
  • 【xsy1230】 树(tree) 点分治+线段树

    题目大意:有一棵$n$个节点的树,点的标号为$1$到$n$。树中的边有边权。给你$m$个询问,每个询问包含三个参数$l,r,pos$,你要求出标号在$l$到$r$之间的所有点中,到节点$pos$距离最近的点离$pos$有多远。

    数据范围:$n,m,l,r,pos≤10^5$,强制在线。

    此题我强制在线两个变量打反了,$wa$了一发。

    我们考虑点分治,对于节点x,我们在节点$x$上种一个线段树,保存以$x$为跟(点分治树树根)的子树内,每个节点距离x的距离。

    对于一组查询,我们直接在点分治树上从下往上条,每跳到一个节点查询一次就可以了。

    时间复杂度:$O(nlog^2 n)$。

     1 #include<bits/stdc++.h>
     2 #define M 100005
     3 #define INF 1e9
     4 using namespace std;
     5 
     6 struct edge{int u,v,next;}e[M*2]={0}; int head[M]={0},use=0;
     7 void add(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
     8 
     9 int siz[M]={0},vis[M]={0},Minn=0,minid=0,n;
    10 void dfssiz(int x,int fa){siz[x]=1;for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa&&vis[e[i].u]==0) dfssiz(e[i].u,x),siz[x]+=siz[e[i].u];}
    11 void dfsmin(int x,int fa,int fsiz){int maxn=fsiz-siz[x]; for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa&&vis[e[i].u]==0) dfsmin(e[i].u,x,fsiz),maxn=max(maxn,siz[e[i].u]);if(maxn<Minn) Minn=maxn,minid=x;}
    12 int makeroot(int x){Minn=M; dfssiz(x,0); dfsmin(x,0,siz[x]); return minid;}
    13 
    14 int lc[M*120]={0},rc[M*120]={0},minn[M*120]={0},root[M]={0},cnt=0;
    15 void updata(int &x,int l,int r,int k,int val){
    16     if(!x) minn[x=++cnt]=INF; minn[x]=min(minn[x],val);
    17     if(l==r) return; int mid=(l+r)>>1;
    18     (k<=mid)?updata(lc[x],l,mid,k,val):updata(rc[x],mid+1,r,k,val);
    19 }
    20 int query(int x,int l,int r,int ll,int rr){
    21     if(x==0||(ll<=l&&r<=rr)) return minn[x];
    22     int mid=(l+r)>>1,res=INF;
    23     if(ll<=mid) res=min(res,query(lc[x],l,mid,ll,rr));
    24     if(mid<rr) res=min(res,query(rc[x],mid+1,r,ll,rr));
    25     return res;
    26 }
    27 void build(int x,int fa,int dis,int &Root){
    28     updata(Root,1,n,x,dis);
    29     for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa&&vis[e[i].u]==0) build(e[i].u,x,dis+e[i].v,Root);
    30 }
    31 
    32 int fa[M]={0};
    33 void solve(int x,int F){
    34     x=makeroot(x); vis[x]=1; fa[x]=F;
    35     build(x,0,0,root[x]);
    36     for(int i=head[x];i;i=e[i].next) if(vis[e[i].u]==0) solve(e[i].u,x);
    37 }
    38 void ReadData(){
    39     minn[0]=INF;
    40     scanf("%d",&n);
    41     for(int i=1;i<n;i++){
    42         int x,y,z; scanf("%d%d%d",&x,&y,&z);
    43         add(x,y,z); add(y,x,z);
    44     }
    45     solve(1,0);
    46 }
    47 
    48 int query(int l,int r,int pos){
    49     int minn=INF;
    50     for(int x=pos;x;x=fa[x]){
    51         int disnow=query(root[x],1,n,l,r);
    52         int dispos=query(root[x],1,n,pos,pos);
    53         minn=min(minn,dispos+disnow);
    54     }
    55     return minn;
    56 }    
    57 void Solve(){
    58     int q,ans=0; scanf("%d",&q);
    59     while(q--){
    60         int l,r,pos; scanf("%d%d%d",&l,&r,&pos); pos^=ans;
    61         printf("%d
    ",ans=query(l,r,pos));
    62     }
    63 }
    64 
    65 int main(){
    66     ReadData();
    67     Solve();
    68 }
  • 相关阅读:
    定义全局时间过滤器
    vue局部过滤器和全局过滤器
    vue-ref指令
    vue进行代码排序
    vue-通过name进行数据过滤
    将vue文档下载到本地预览
    由于vue的for循环id并不严谨,提高id严谨性
    vue指令v-for报错:Elements in iteration expect to have 'v-bind:key' directives.eslint-plugin-vue
    FlowPortal BPM历史版本升级说明
    102从 Outlook 中将电子邮件、联系人和日历导出到 .pst 文件
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10398002.html
Copyright © 2011-2022 走看看