P17141 [NOI 2026] 传送
Genius_Star · · 题解
来个根号做法,感觉很显然啊。
思路:
显然,策略一定是随机一会儿然后再沿着最短路径走:
- 容易感性理解,随机传送等于随机重开,走了一段后再重开显然不如一开始就重开优秀。
那么显然,对于
-
外面的点随机到
S 的概率是\frac{|S|}{n} ,那么随机到S 的期望次数是\frac{n}{|S|} 。 -
里面的点走到
v 的期望次数是\frac{1}{|S|} \sum_{i \in S} dis(i, v) 。 -
则答案是:
于是有了一个
考虑优化,把上面式子用
推一下
考虑
那么可以想到二分,然后只需要查询
但是实际上不需要那么麻烦,我们都推出来
然后怎么做?你需要数一个点
对于
注意询问的时候如果
完整代码:
#include<bits/stdc++.h>
#define lowbit(x) x & (-x)
#define ls(k) k << 1
#define rs(k) k << 1 | 1
#define fi first
#define se second
#define ctz(x) __builtin_ctz(x)
#define popcnt(x) __builtin_popcount(x)
#define open(s1, s2) freopen(s1, "r", stdin), freopen(s2, "w", stdout);
using namespace std;
typedef __int128 __;
typedef long double lb;
typedef double db;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long long ll;
const int N = 5e5 + 10, M = 1e6 + 10;
inline ll read(){
ll x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')
f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int c, n, m, cnt;
int du[N], head[N];
struct edge{
int to, nxt;
}e[M];
inline void add(int u, int v){
e[++cnt] = {v, head[u]};
head[u] = cnt;
e[++cnt] = {u, head[v]};
head[v] = cnt;
++du[u], ++du[v];
}
namespace Tree{
int siz[N], top[N], son[N], dep[N], fa[N];
inline void init(){
for(int i = 0; i < n; ++i)
son[i] = n;
}
inline void dfs1(int u, int f){
siz[u] = 1;
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
if(v == f)
continue;
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]])
son[u] = v;
}
}
inline void dfs2(int u, int k){
top[u] = k;
if(!son[u])
return ;
dfs2(son[u], k);
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
if(v == fa[u] || v == son[u])
continue;
dfs2(v, v);
}
}
inline int LCA(int u, int v){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]])
swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
inline int dis(int u, int v){
return dep[u] + dep[v] - 2 * dep[LCA(u, v)];
}
}
bool vis[N];
int mxd[N];
int dp[3][N], s[N], all[N];
vector<pair<int, int>> Q[N];
std::vector<std::pair<long long, int>> teleport(int _c, int _n, int _m, std::vector<int> u, std::vector<int> v, std::vector<int> x, std::vector<int> y){
c = _c, n = _n, m = _m;
for(int i = 0; i < n - 1; ++i)
add(u[i], v[i]);
Tree::init();
Tree::dfs1(0, 0);
Tree::dfs2(0, 0);
for(int i = 0; i < m; ++i)
Q[y[i]].push_back({x[i], i});
int lim = min((int)sqrt(2 * n) + 1, n);
// cerr << lim << '\n';
for(int i = 0; i <= lim; ++i){
int now = i % 3;
if(!i){
for(int u = 0; u < n; ++u){
dp[now][u] = 1;
s[u] += dp[now][u];
all[u] += s[u];
}
continue;
}
if(i == 1){
for(int u = 0; u < n; ++u){
dp[now][u] = du[u];
s[u] += dp[now][u];
all[u] += s[u];
if(all[u] >= n && !mxd[u])
mxd[u] = i, vis[u] = 1;
}
continue;
}
int pre = (i - 1) % 3, ppre = (i - 2) % 3;
for(int u = 0; u < n; ++u)
dp[now][u] = -(du[u] - (i != 2)) * dp[ppre][u];
for(int u = 1; u < n; ++u)
dp[now][u] += dp[pre][Tree::fa[u]], dp[now][Tree::fa[u]] += dp[pre][u];
for(int u = 0; u < n; ++u){
if(vis[u])
continue;
s[u] += dp[now][u], all[u] += s[u];
if(all[u] >= n && !mxd[u])
mxd[u] = i, vis[u] = 1;
}
}
vector<pair<long long, int>> ans(m);
for(int u = 0; u < n; ++u){
if(Q[u].empty())
continue;
int d = mxd[u];
int a = n + (d + 1) * s[u] - all[u], b = s[u];
// cerr << u << ' ' << mxd[u] << ' ' << all[u] << ' ' << a << ' ' << b << '\n';
int g = __gcd(a, b);
a /= g, b /= g;
for(auto t : Q[u]){
int v = t.fi, id = t.se;
int dis = Tree::dis(u, v);
if(a < 1ll * b * dis)
ans[id] = {a, b};
else
ans[id] = {dis, 1};
}
}
return ans;
}
int main(){
c = read(), n = read(), m = read();
vector<int> u, v;
for(int i = 0; i < n - 1; ++i){
u.push_back(read());
v.push_back(read());
}
vector<int> x, y;
for(int i = 0; i < m; ++i){
x.push_back(read());
y.push_back(read());
}
vector<pair<long long, int>> ans = teleport(c, n, m, u, v, x, y);
puts("7c9f2e4a61b8d305a4e6f93c0d12b7aa");
for(auto t : ans){
write(t.fi);
putchar(' ');
write(t.se);
putchar('\n');
}
puts("7c9f2e4a61b8d305a4e6f93c0d12b7aa");
return 0;
}