【2018 12月集训 Day2】小奇的危机

给定一棵树,有若干次询问,每次给定 $l,r,x$,求一个点 $y$,满足 $l \le y \le r$,且最小化 $\text{dis}(x,y)$

$n,q \le 10^5, l \le r$,任意两个点的距离不超过 $10^9$

有一个十分自然的鬼畜想法就是把每个询问 $[l,r]$,拆分成 $\log n$ 个区间放到线段树上,然后依次访问线段树的每一个区间

之后对当前区间(假设是 $[L,R]$)的所有询问点和下标在 $[L,R]$ 的点建立虚树

之后就相当于给定一棵树,有一些关键点,问所有点到所有关键点的距离最小值是多少

这个可以跑两次树上动态规划来解决掉

之后就能过了……时间复杂度 $O((n+q) \log^2 n)$

如果要求强制在线呢?其实也很简单(不知道对不对……口胡一下……)……

这回就相当于给定一棵树,树上有关键点,还有若干次询问,每次给定一个点,问这个点到树上所有关键点的最近距离

这样只需要找到这个点和树的两个交点就行了,显然要么这个点在虚树外,要么在虚树上,要么在虚树上某两个点之间

对于第一种情况,只可能是该点的子树中有虚树的根,或者该点到原树的根节点的路径上有虚树的根,要么就是该点和虚树的根节点的最近公共祖先在该点到原树的根上

对于第二种情况,直接输出预处理的答案就行了

对于第三种情况,直接查找虚树上的这两个点后更新答案就行了

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 struct FastIO {
  5     static const int S = 2e7;
  6     int wpos;
  7     char wbuf[S];
  8     FastIO() : wpos(0) {}
  9     inline int xchar() {
 10         static char buf[S];
 11         static int len = 0, pos = 0;
 12         if (pos == len)
 13             pos = 0, len = fread(buf, 1, S, stdin);
 14         if (pos == len) exit(0);
 15         return buf[pos++];
 16     }
 17     inline int operator () () {
 18         int c = xchar(), x = 0;
 19         while (c <= 32) c = xchar();
 20         for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
 21         return x;
 22     }
 23     inline void wchar(int x) {
 24         if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
 25         wbuf[wpos++] = x;
 26     }
 27     inline void operator () (int x) {
 28         char s[24];
 29         int n = 0;
 30         while (x || !n) s[n++] = '0' + x % 10, x /= 10;
 31         while (n--) wchar(s[n]);
 32         wchar('\n');
 33     }
 34     ~FastIO()
 35     {
 36         if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
 37     }
 38 } io;
 39 
 40 const int N = 100000 + 10;
 41 
 42 int n, q; 
 43 
 44 int _head[N], _rest[N * 2], _to[N * 2], _w[N * 2];
 45 void lk(int u, int v, int w) {
 46     static int tot = 0;
 47     _to[++ tot] = v, _w[tot] = w, _rest[tot] = _head[u], _head[u] = tot;
 48     _to[++ tot] = u, _w[tot] = w, _rest[tot] = _head[v], _head[v] = tot;
 49 }
 50 
 51 struct T {
 52     int id, x;
 53 };
 54 
 55 vector<T> que[N * 10];
 56 
 57 #define lc (id << 1)
 58 #define rc (id << 1 | 1)
 59 void poi(int id, int l, int r, int ql, int qr, T t) {
 60     int mid = (l + r) >> 1;
 61     if(ql <= l && r <= qr) {
 62         que[id].push_back(t);
 63     } else if(qr <= mid) {
 64         poi(lc, l, mid, ql, qr, t);
 65     } else if(ql >= mid + 1) {
 66         poi(rc, mid + 1, r, ql, qr, t);
 67     } else {
 68         poi(lc, l, mid, ql, mid, t);
 69         poi(rc, mid + 1, r, mid + 1, qr, t);
 70     }
 71 }
 72 
 73 int ans[N], beg_dfn[N], end_dfn[N], clk, dep[N], len[N];
 74 int fa[N][21];
 75 
 76 int getlca(int u, int v) {
 77     if(dep[u] < dep[v]) swap(u, v);
 78     for(int i = 20 ; ~ i ; -- i)
 79         if(dep[fa[u][i]] >= dep[v])
 80             u = fa[u][i];
 81     if(u == v) return u;
 82     for(int i = 20 ; ~ i ; -- i)
 83         if(fa[u][i] != fa[v][i])
 84             u = fa[u][i], v = fa[v][i];
 85     return fa[u][0];
 86 }
 87 
 88 void getdfn(int u, int fa) {
 89     :: fa[u][0] = fa;
 90     for(int i = 1 ; i <= 20 ; ++ i)
 91         :: fa[u][i] = :: fa[:: fa[u][i - 1]][i - 1];
 92     
 93     beg_dfn[u] = ++ clk;
 94     dep[u] = dep[fa] + 1;
 95     for(int i = _head[u] ; i ; i = _rest[i]) {
 96         int v = _to[i], w = _w[i];
 97         if(v == fa) continue;
 98         len[v] = len[u] + w;
 99         getdfn(v, u);
100     }
101     end_dfn[u] = clk;
102 }
103 
104 int a[N * 10], top, root, spe[N];
105 int cmp(int x, int y) { return beg_dfn[x] < beg_dfn[y]; }
106 
107 const int inf = 0x3f3f3f3f;
108 int f[N], h[N];
109 
110 int head[N], rest[N * 2], to[N * 2], w[N * 2], tot;
111 
112 int thev[N], thew[N], the_top;
113 
114 namespace TreeDP {
115     void dfs(int u, int fa) {
116         f[u] = inf;
117         if(spe[u]) f[u] = 0;
118         for(int i = head[u] ; i ; i = rest[i]) {
119             int v = to[i], w = :: w[i];
120             if(v == fa) continue;
121             dfs(v, u);
122             f[u] = min(f[u], f[v] + w);
123         }
124     }
125     
126     void go(int u, int fa) {
127         if(u == root) h[u] = inf;
128         if(spe[u]) h[u] = 0;
129         
130         the_top = 0;
131         for(int i = head[u] ; i ; i = rest[i]) {
132             int v = to[i], w = :: w[i];
133             if(v == fa) continue;
134             thev[++ the_top] = v;
135             thew[the_top] = w;
136         }
137         
138         int themn = inf;
139         for(int i = 1 ; i <= the_top ; ++ i) {
140             int v = thev[i], w = thew[i];
141             h[v] = h[u] + w;
142             h[v] = min(h[v], themn + w);
143             themn = min(themn, f[v] + w);
144         }
145         themn = inf;
146         for(int i = the_top ; i >= 1 ; -- i) {
147             int v = thev[i], w = thew[i];
148             h[v] = min(h[v], themn + w);
149             themn = min(themn, f[v] + w);
150         }
151         for(int i = head[u] ; i ; i = rest[i]) {
152             int v = to[i];
153             if(v == fa) continue;
154             go(v, u);
155         }
156     }
157     
158     void sol(int root) {
159         dfs(root, 0);
160         go(root, 0);
161     }
162 }
163 
164 void add(int u, int v, int w) {
165     to[++ tot] = v, :: w[tot] = w, rest[tot] = head[u], head[u] = tot;
166     to[++ tot] = u, :: w[tot] = w, rest[tot] = head[v], head[v] = tot;
167 }
168 
169 int sta[N], statop;
170 
171 void dfs(int id, int l, int r) {
172     int mid = (l + r) >> 1;
173     
174     if(que[id].size()) {
175         top = 0;
176         for(int i = l ; i <= r ; ++ i) {
177             a[++ top] = i;
178             spe[i] = 1;
179         }
180         for(T t: que[id]) {
181             a[++ top] = t.x;
182         }
183         sort(a + 1, a + 1 + top, cmp);
184         top = unique(a + 1, a + 1 + top) - a - 1;
185         
186         for(int i = top ; i >= 2 ; -- i)
187             a[++ top] = getlca(a[i], a[i - 1]);
188         sort(a + 1, a + 1 + top, cmp);
189         top = unique(a + 1, a + 1 + top) - a - 1;
190         
191         tot = 0;
192         for(int i = 1 ; i <= top ; ++ i)
193             head[a[i]] = 0;
194         root = a[1];
195         
196         statop = 0;
197         for(int i = 1 ; i <= top ; ++ i) {
198             int u = a[i];
199             while(statop && end_dfn[sta[statop]] < beg_dfn[u]) -- statop;
200             if(statop) {
201                 add(sta[statop], u, len[u] - len[sta[statop]]);
202             }
203             sta[++ statop] = u;
204         }
205         
206         TreeDP :: sol(root);
207         
208         for(T t: que[id]) {
209             int ansid = t.id, u = t.x;
210             ans[ansid] = min(ans[ansid], min(f[u], h[u]));
211         }
212         
213         for(int i = l ; i <= r ; ++ i) spe[i] = 0;
214     }
215     if(l != r) dfs(lc, l, mid), dfs(rc, mid + 1, r);
216 }
217 
218 int main() {
219     n = io();
220     for(int i = 1, u, v, w ; i < n ; ++ i) {
221         u = io(), v = io(), w = io();
222         lk(u, v, w);
223     }
224     getdfn(1, 0);
225     q = io();
226     
227     memset(ans, 0x3f, sizeof(int) * (q + 5));
228     
229     for(int i = 1, l, r, x ; i <= q ; ++ i) {
230         l = io(), r = io(), x = io();
231         poi(1, 1, n, l, r, (T) { i, x });
232     }
233     
234     dfs(1, 1, n);
235     for(int i = 1 ; i <= q ; ++ i) {
236         io(ans[i]);
237     }
238 }
【2018 12月集训 Day2】小奇的危机

posted @ 2018-12-14 12:05 KingSann 阅读(...) 评论(...) 编辑 收藏