题意
给出一棵树,每次询问一个点$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 }