当前位置: 首页 > news >正文

[GDKOI2023 提高组] 游戏 题解

一种比较简短的写法:

拉出直径,再在直径的每一个点上跑一下最长链,为 $ mx_i$

这里设三点的路径交点为 \(rt\)

假设 \(rt \rightarrow u,v,w\) 的距离为 \(dis1,dis2,dis3\)

容易知道 \(dis1 = (x+y-z)/2,dis2 = (-x+y+z)/2,dis3 = (x-y+z)/2\)

在直径上的 \([dis1+1,len-dis2]\) 中选择 \(mx\) 最大值判断是否大于等于 \(dis3\)

若成立,则在 \([dis2+1,len-dis1]\) 中选择 \(mx\) 最大值判断是否大于等于 \(dis3\)

明显这样做是在 \(dis1\ge dis2\ge dis3\) 时成立,若 \(dis1,dis2,dis3\) 不满足递减关系,先排序,最后调整关系即可。

时间复杂度 \(O(n \log n +q)\),常熟较小,比次优解快一半。

放一个未卡常的个人觉得比较清新的代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2E5+5;
int n,q,dep[N],rt,fa[N],st[N][21],mx[N],lg[N],vis[N],a[4],b[4];
vector<int>e[N],g,h[N];
int get(int x,int y){return mx[x]>mx[y]?x:y;
}
void dfs(int u,int F){fa[u]=F;dep[u]=dep[F]+1;if(dep[u]>dep[rt])rt=u;for(int v:e[u])if(v!=F&&!vis[v])dfs(v,u);
}
int query(int l,int r){int tmp=lg[r-l+1];return get(st[l][tmp],st[r+1-(1<<tmp)][tmp]);
}
bool cmp(int x,int y){return a[x]>a[y];
}
int main(){freopen("game.in", "r", stdin);freopen("game.out", "w", stdout);scanf("%d",&n);for(int i=1,u,v;i<n;i++){scanf("%d%d",&u,&v);e[u].push_back(v),e[v].push_back(u);}dfs(1,0);dfs(rt,0);while(rt)vis[rt]=1,g.push_back(rt),rt=fa[rt];for(int i=0;i<g.size();i++){int x=g[i];rt=0;dep[0]=-1;st[i+1][0]=i;dfs(x,0);mx[i]=dep[rt];while(rt)h[i].push_back(rt),rt=fa[rt];reverse(h[i].begin(),h[i].end());}for(int i=1;i<=20;i++)for(int j=1;j+(1<<i-1)<=g.size();j++)st[j][i] = get(st[j][i-1],st[j+(1<<i-1)][i-1]);for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;scanf("%d",&q);while(q--){int u,v,w;for(int i=1;i<=3;i++)scanf("%d",a+i),b[i]=i;sort(b+1,b+4,cmp);int tmp1= (a[b[1]] + a[b[2]] - a[b[3]])/2;int tmp2= a[b[1]] - tmp1;int tmp3= a[b[2]] - tmp1;int tmp= query(tmp1+1,g.size()-tmp2);if(mx[tmp] >= tmp3){u = g[tmp-tmp1];v = g[tmp+tmp2];w = h[tmp][tmp3];} else {tmp= query(tmp2+1,g.size()-tmp1);v = g[tmp-tmp2];u = g[tmp+tmp1];w = h[tmp][tmp3];}if (b[1] == 1 && b[2] == 2)printf("%d %d %d\n", u, v, w);if (b[1] == 1 && b[2] == 3)printf("%d %d %d\n", v, u, w);if (b[1] == 2 && b[2] == 1)printf("%d %d %d\n", u, w, v);if (b[1] == 2 && b[2] == 3)printf("%d %d %d\n", v, w, u);if (b[1] == 3 && b[2] == 1)printf("%d %d %d\n", w, u, v);if (b[1] == 3 && b[2] == 2)printf("%d %d %d\n", w, v, u);}return 0;}
http://www.zskr.cn/news/8276.html

相关文章:

  • 实用指南:AI推理范式:从CoT到ReAct再到ToT的进化之路
  • ctfshow web入门 信息搜集
  • CTFWEB姿势总结
  • 详细介绍:架构思维:分布式缓存实战
  • 规模化加速AI:从用户、开发者到企业的深度策略解析
  • 最新IDEA 2025 专业版破解永久破解教程(附资源)intellij IDEA
  • AtCoder ABC423F - Loud Cicada 题解 容斥原理
  • 1756:八皇后
  • 矩阵置零-leetcode
  • 重新开始配置hadoop等
  • 实用指南:kafka 原理详解
  • 网络编程-HTTP - 详解
  • 网络流初步浅谈:EK与Dinic
  • Spring框架事件驱动架构核心注解之@EventListener - 指南
  • FreeRTOS SMP 资料收集
  • 2025.9.19——卷9-10选择
  • ctfshow web 入门 php特性
  • 详细介绍:Git如何无痕上传当前项目最新状态从当前远程到另一个远程
  • 【qt】全局事件总线
  • 深入解析:React Device Detect 完全指南:构建响应式跨设备应用的最佳实践
  • ctfshow web89
  • ctfshow web90
  • web360
  • hbase的安装应用
  • ctfshow web357
  • 深入解析:Java全栈开发面试实录:从基础到微服务的实战解析
  • 谁会不爱低温静音 性能还更强的!酷睿Ultra 5 230F vs 锐龙5 9600X生产力、功耗、温度全方位对比
  • WPF viewmodel retrieve matched view /window
  • ctfshow web353
  • fxztgxj5.dll fxzrs4qj.dll fxztgxa5.dll fxzrs3qj.dll fxzpmc1.dll fxzrs2qj.dll fxzmpxa5.dll - 实践