这道题需要转化,换根和卡常。
首先将集合中的点拉出来,找它们的直径
不需要什么虚树,随便挑一个集合里的点为根,做一遍dfs,找最远点x(要在集合里),以x为根重复以上操作,找到最远点y,x-y就是题解所谓“集合中点的直径”
然后,f[i]f[i]f[i]值可以转化成i与直径中点距离加上直径长度的一半
问题来了,如果有直径长度单数情况怎么办?
方法1(题解):发现这时中点在边上,如果中点在x-y边上,考虑新建点z,x,y分别与z连边,长度为1/2,此时z就是中点,为了避免小数,将所有边权*2
方法2(By FK)直径长度/2上取整,此时不必新建点,将x,y看成中点即可
我们在中点处(两个中点则两个中点都要)打上tag标记,代表直径长度/2上取整。
不可能nq复杂度更新f数组,考虑换根。
先从1开始dfs,那么有
ans[t]=min(min(ans[son]+1),tag[t])ans[t]=min(min(ans[son]+1),tag[t])ans[t]=min(min(ans[son]+1),tag[t])
然后换根,则有
ans[f[k][1]]=min(ans[f[k][1],ans[t]+1)ans[f[k][1]]=min(ans[f[k][1],ans[t]+1)ans[f[k][1]]=min(ans[f[k][1],ans[t]+1)
本来需要消除儿子对根的影响,但是min并无所谓,sum就要
其实,理论上呢,这道题应该就结束了。
但是,这道题卡常加上OJ栈空间不够,让它十分恶心!
首先,你会发现自己RE78(如果不WA)
原因:OJ栈空间不够
解决方案:人工栈
然后就是各种各样的TLE
两点间距离可以用ST表预处理,虽然预处理是log的,但查询是O(1)的
此时,如果你还TLE,卡常吧
方法包括但不限于register,inline,if语句改三元运算符等
然后,运气好的话,你就可以AC了
或者依靠OJ的随机摆动,找到快的评测机AC
例如某HZH大佬交了4次摆动一下就切了
正负400ms都是常事,不要惊讶。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define mem(x) memset(x,0,sizeof(x))
#define min(a,b) a<b?a:b
#define R register
#define I inline
using namespace std;
int xl[600005],z[300005],tag[300005],ans[300005],a[300005],dep[300005],b[300005][20],mi[20],f[300005][3],q[300005];
int st[600005][20],lc[600005][20],lg[600005],type[300005],zt[300005],zson[300005],zk[300005],mn[300005],in[300005],out[300005];
int i,j,k,m,n,o,p,l,s,t,times,g,h,top,tot;
I char nc(){static char buf[100000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
I void read(int &x){char ch=nc();x=0;while (!(ch>='0'&&ch<='9')) ch=nc();while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=nc();
}
I void insert(R int x,R int y) {f[++t][1]=y,f[t][2]=q[x],q[x]=t;}
int ST(int x,int y)
{R int k=lg[y-x+1];return st[x][k]<st[y-(1<<k)+1][k]?lc[x][k]:lc[y-(1<<k)+1][k];
}
int getlca(int x,int y)
{if (in[x]<=in[y]&&out[y]<=out[x]) return x;if (in[y]<=in[x]&&out[x]<=out[y]) return y;return in[x]<=out[y]?ST(in[x],out[y]):ST(in[y],out[x]);
}
I int getdis(R int x,R int y) {R int lca=getlca(x,y);return dep[x]+dep[y]-2*dep[lca];}
I int jump(R int x,R int y,R int lca,R int g)
{if (dep[x]-dep[lca]>=g){for (R int i=18;i>=0;i--)(g>=mi[i])?g-=mi[i],x=b[x][i]:g=g;return x; } else {g-=(dep[x]-dep[lca]);x=y;g=dep[y]-dep[lca]-g;for (R int i=18;i>=0;i--)(g>=mi[i])?g-=mi[i],x=b[x][i]:g=g;return x; }
}
I int find(R int x)
{R int s=-1,pos=0;for (R int i=1;i<=m;i++){R int o=getdis(a[i],x);(o>s)?s=o,pos=i:o=o;}return pos;
}
I void dg(R int t)
{type[++top]=0,zt[top]=t;while (top){wyd:;R int t=zt[top],son=zson[top],k=zk[top];if (type[top]==1) goto WYD;for (k=q[t];k;k=f[k][2]){son=f[k][1];ans[f[k][1]]=min(ans[f[k][1]],ans[t]+1),zt[top]=t,zson[top]=son,zk[top]=k,type[top]=1;type[++top]=0,zt[top]=son;goto wyd;WYD:;mn[t]=min(mn[t],ans[f[k][1]]+1);}ans[t]=min(mn[t],tag[t]);top--;}
}
I void dfs(R int t)
{type[++top]=0,zt[top]=t;while (top){wyd:;R int t=zt[top],son=zson[top],k=zk[top];if (type[top]==1) goto WYD;for (k=q[t];k;k=f[k][2]){son=f[k][1];ans[f[k][1]]=min(ans[f[k][1]],ans[t]+1),zt[top]=t,zson[top]=son,zk[top]=k,type[top]=1;type[++top]=0,zt[top]=son;goto wyd;WYD:;}top--;}
}
I void pre(R int t)
{type[++top]=0,zt[top]=t;while (top){wyd:;R int t=zt[top],son=zson[top],k=zk[top];if (type[top]==1) goto WYD;tot++;in[t]=tot<in[t]?tot:in[t],out[t]=(tot>out[t])?tot:out[t],xl[tot]=t;for (k=q[t];k;k=f[k][2]){son=f[k][1];dep[son]=dep[t]+1;zt[top]=t,zson[top]=son,zk[top]=k,type[top]=1;type[++top]=0,zt[top]=son;goto wyd;WYD:;tot++;in[t]=tot<in[t]?tot:in[t],out[t]=(tot>out[t])?tot:out[t],xl[tot]=t;}top--;}
}
void prepare(){lg[0]=-1;for (R int i=1;i<=tot;i++) lg[i]=lg[i>>1]+1;for (R int i=1;i<=19;i++)for (R int j=1;j+(1<<i)-1<=tot;j++){int opt=st[j][i-1]<st[j+(1<<(i-1))][i-1];lc[j][i]=(opt>0)?lc[j][i-1]:lc[j+(1<<(i-1))][i-1];st[j][i]=(opt>0)?st[j][i-1]:st[j+(1<<(i-1))][i-1];}
}
signed main()
{freopen("stone.in","r",stdin);freopen("stone.out","w",stdout);read(n);dep[1]=1;for (R int i=mi[0]=1;i<=19;i++) mi[i]=mi[i-1]*2;for (R int i=2;i<=n;i++) read(o),insert(o,i),b[i][0]=o;for (R int i=1;i<=18;i++)for (R int j=1;j<=n;j++)b[j][i]=b[b[j][i-1]][i-1];memset(in,60,sizeof(in));pre(1);for (i=1;i<=tot;i++) st[i][0]=dep[xl[i]],lc[i][0]=xl[i];prepare();read(times);memset(tag,60,sizeof(tag));while (times--){read(m);for (R int i=1;i<=m;i++) read(a[i]);g=find(a[1]),h=find(a[g]);g=a[g],h=a[h];int dis=getdis(g,h),lca=getlca(g,h);if (!(dis&1)){R int ad=dis>>1,mid=jump(g,h,lca,ad);tag[mid]=min(tag[mid],ad);} else {R int ad=dis>>1,mid1=jump(g,h,lca,ad),mid2=jump(h,g,lca,ad);tag[mid1]=min(tag[mid1],ad+1),tag[mid2]=min(tag[mid2],ad+1);}}memset(ans,60,sizeof(ans)),memset(mn,60,sizeof(mn));mem(zt),mem(zson),mem(type),mem(zk);top=0;dg(1);mem(zt),mem(zson),mem(type),mem(zk);top=0;dfs(1);for (R int i=1;i<=n;i++) printf("%d\n",ans[i]);return 0;
}

JZOJ6893. 【2020.11.25提高组模拟】小 T 与灵石(stone)题解相关推荐

  1. 6848. 【2020.11.03提高组模拟】融入社会的计划

    Description Input Output 一行一个整数表示答案. upd:  无解输出-1. Sample Input Sample Input1 6 6 13 11 1 1 4 5 5 Sa ...

  2. 6846. 【2020.11.02提高组模拟】旅人1970

    Description Input Output Sample Input Sample Input1 25 4 4 1 2 3 2 1 1 1 2 Sample Output Sample Outp ...

  3. JZOJ6828. 【2020.10.25提高组模拟】幂

    Description TTT组数据,T≤1e5,n≤1e7T\le1e5,n\le1e7T≤1e5,n≤1e7 Solution 好家伙,最下面的数据范围居然是这样的: 直接以为卡特兰数乘上个组合数 ...

  4. 【2020.11.30提高组模拟】剪辣椒(chilli)

    剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...

  5. gmoj 6860. 【2020.11.14提高组模拟】鬼渊传说

    题目 Time Limits: 1000 ms Memory Limits: 518400 KB 简要题意 给出一个网格图,每个格子有黑白二色,求有多少个子矩形满足将其挖出来后恰好有一个黑色四连通块且 ...

  6. 【2020.12.03提高组模拟】袋鼠

    题目 题目描述 你知道吗?乌拉圭的人口有345.7万,同时,仅澳大利亚就有4700万只袋鼠. 袋鼠决定入侵乌拉圭.袋鼠们将在平原上布阵,平原被划分成 n×mn \times mn×m 的网格. 每个格 ...

  7. 6810. 【2020.10.05提高组模拟】路哥

    Description Input Output Sample Input Sample Input1 3 1 1 1 1 1 2 2 3 Sample Input2 9 4 0 0 1 4 1 2 ...

  8. 提高组模拟试题七第二试 佐佐小次郎

    提高组模拟试题七第二试 佐佐小次郎 Time Limit:10000MS  Memory Limit:65536K Total Submit:26 Accepted:26 Case Time Limi ...

  9. 第一届『Citric杯』NOIP提高组模拟赛 题解

    [官方题解]第一届『Citric杯』NOIP提高组模拟赛 题解 第一题 柠檬超市 这题是本次模拟赛的送分题.做法显然. 但是注意此题有一个陷阱: 注意W和C的规模都是10^9,所以如果直接用doubl ...

最新文章

  1. hdu 4937 Lucky Number(数学题 进制转换)2014多校训练第7场
  2. C语言链表的来源分析
  3. python 什么是原类_Python 什么是元类(metaclasses)?
  4. 细数改善WPF应用程序性能的10大方法
  5. 与0xf2值相等的是python_腾讯笔试题涵盖的基础知识
  6. 电脑时间校对器_笔记本电脑如何保养?华为教你五招轻松延长使用时间
  7. confirm + if 逻辑判断 -代码篇
  8. .5-浅析webpack源码之入口函数
  9. 数据交换-电路/报文/分组交换
  10. Intel的AVX2指令集解读
  11. Linq To EF (添加记录后获取添加的自增ID和叫“ID”的列不是自增列不让插入的问题)...
  12. 数据结构课程设计(基于AVL树的身份证管理系统)
  13. 中端存储和高端存储的区别
  14. iPhone手机ipa破解补丁安装方法和ipa软件游戏安装教程(1)
  15. 动态DNS的定义以及优缺点有哪些
  16. 初学者学习插画原画以后就业方向有哪些?和大家聊聊插画原画师就业、薪资等
  17. 积分竟然比微分早了1300年!一文讲清积分的历史
  18. 渡一教育公开课web前端开发JavaScript精英课学习笔记(二十九)JavaScript 骇客帝国
  19. Win2003集群简介
  20. 3.Spark的安装(华为云学习笔记,Spark编程基础,大数据)

热门文章

  1. Buzzer Speaker
  2. 同时登录多个飞信客户端的方法
  3. Tshock的config.json配置文件翻译(对应5.1.2版本)
  4. 统计学生平均成绩。使用静态成员函数。如果不将average函数定义为静态成员函数行不行?程序能否通过编译?需要作什么修改?为什么要用静态成员函数?请分析其理由。
  5. python求三个数平均值_Python操作Excel教程-average函数求平均值
  6. 推荐开源矢量绘图软件Inkscape
  7. 市盈率仍是判断股市泡沫的重要标准
  8. Android版Office App,微软office android app
  9. Bezier曲线切割
  10. 16. DICOM图像显示-DCMTK-cda转dicom