[LOJ6145]Easy

题意
给出一棵树,每次询问一个点$x$
到编号在$[l,r]$中的点的距离的最小值。
$n,q\le 10^5$

大概是最简单的动态点分治了,注意开大数组即可,如果改成求最大值这道题会有意思很多

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #define M 100010
  5 #define ls ch[node][0]
  6 #define rs ch[node][1]
  7 using namespace std;
  8 int n,m,num,cnt,root,S;
  9 int head[M],son[M],sz[M],top[M],deep[M],fa[M],f[M],size[M],maxn[M],dis[M],rt[M];
 10 int val[M<<7],ch[M<<7][2];bool vis[M];
 11 struct point{int to,next,dis;}e[M<<1];
 12 void add(int from,int to,int dis) {
 13     e[++num].next=head[from];
 14     e[num].to=to;
 15     e[num].dis=dis;
 16     head[from]=num;
 17 }
 18 void dfs1(int x) {
 19     sz[x]=1;deep[x]=deep[fa[x]]+1;
 20     for(int i=head[x];i;i=e[i].next) {
 21         int to=e[i].to;
 22         if(to==fa[x]) continue;
 23         fa[to]=x,dis[to]=dis[x]+e[i].dis;
 24         dfs1(to),sz[x]+=sz[to];
 25         if(sz[son[x]]<sz[to]) son[x]=to;
 26     }
 27 }
 28 void dfs2(int x,int tp) {
 29     top[x]=tp;
 30     if(son[x]) dfs2(son[x],tp);
 31     for(int i=head[x];i;i=e[i].next)
 32         if(e[i].to!=fa[x]&&e[i].to!=son[x])
 33             dfs2(e[i].to,e[i].to);
 34 }
 35 int lca(int x,int y) {
 36     while(top[x]!=top[y]) {
 37         if(deep[top[x]]<deep[top[y]]) swap(x,y);
 38         x=fa[top[x]];
 39     }
 40     return deep[x]<deep[y]?x:y;
 41 }
 42 int getdis(int x,int y) {
 43     return dis[x]+dis[y]-2*dis[lca(x,y)];
 44 }
 45 void getroot(int x,int fa) {
 46     size[x]=1;maxn[x]=0;
 47     for(int i=head[x];i;i=e[i].next) {
 48         int to=e[i].to;
 49         if(to==fa||vis[to]) continue;
 50         getroot(to,x),size[x]+=size[to];
 51         maxn[x]=max(maxn[x],size[to]);
 52     }
 53     maxn[x]=max(maxn[x],S-size[x]);
 54     if(maxn[x]<maxn[root]) root=x;
 55 }
 56 void solve(int x,int ff) {
 57     vis[x]=true,f[x]=ff;
 58     for(int i=head[x];i;i=e[i].next) {
 59         int to=e[i].to;
 60         if(vis[to]) continue;
 61         S=size[to],root=0,getroot(to,0);
 62         solve(root,x);
 63     }
 64 }
 65 void update(int node) {
 66     if(ls) val[node]=min(val[node],val[ls]);
 67     if(rs) val[node]=min(val[node],val[rs]);
 68 }
 69 void insert(int &node,int l,int r,int x,int v) {
 70     if(!node) node=++cnt,val[node]=1e9;
 71     if(l==r) {
 72         val[node]=v;return;
 73     }
 74     int mid=(l+r)/2;
 75     if(x<=mid) insert(ls,l,mid,x,v);
 76     else insert(rs,mid+1,r,x,v);
 77     update(node);
 78 }
 79 int query(int node,int l,int r,int l1,int r1) {
 80     if(!node) return 1e9;
 81     if(l1<=l&&r1>=r) return val[node];
 82     int mid=(l+r)/2,ans=1e9;
 83     if(l1<=mid) ans=min(ans,query(ls,l,mid,l1,r1));
 84     if(r1>mid) ans=min(ans,query(rs,mid+1,r,l1,r1));
 85     return ans;
 86 }
 87 void pushin(int x) {
 88     for(int i=x;i;i=f[i])
 89         insert(rt[i],1,n,x,getdis(x,i));
 90 }
 91 int ask(int x,int l,int r) {
 92     int ans=1e9;
 93     for(int i=x;i;i=f[i])
 94         ans=min(ans,getdis(x,i)+query(rt[i],1,n,l,r));
 95     return ans;
 96 }
 97 int main() {
 98     scanf("%d",&n);
 99     for(int i=1;i<n;i++) {
100         int x,y,z;scanf("%d%d%d",&x,&y,&z);
101         add(x,y,z),add(y,x,z);
102     }
103     dfs1(1),dfs2(1,1);
104     S=maxn[0]=n,getroot(1,0),solve(root,0);
105     for(int i=1;i<=n;i++) pushin(i);
106     scanf("%d",&m);
107     for(int i=1;i<=m;i++) {
108         int l,r,x;scanf("%d%d%d",&l,&r,&x);
109         printf("%d\n",ask(x,l,r));
110     }
111     return 0;
112 }

 

posted @ 2018-11-28 08:59  Slr  阅读(232)  评论(0编辑  收藏  举报