JZOJ6893. 【2020.11.25提高组模拟】小 T 与灵石(stone)题解
这道题需要转化,换根和卡常。
首先将集合中的点拉出来,找它们的直径
不需要什么虚树,随便挑一个集合里的点为根,做一遍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)题解相关推荐
- 6848. 【2020.11.03提高组模拟】融入社会的计划
Description Input Output 一行一个整数表示答案. upd: 无解输出-1. Sample Input Sample Input1 6 6 13 11 1 1 4 5 5 Sa ...
- 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 ...
- JZOJ6828. 【2020.10.25提高组模拟】幂
Description TTT组数据,T≤1e5,n≤1e7T\le1e5,n\le1e7T≤1e5,n≤1e7 Solution 好家伙,最下面的数据范围居然是这样的: 直接以为卡特兰数乘上个组合数 ...
- 【2020.11.30提高组模拟】剪辣椒(chilli)
剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...
- gmoj 6860. 【2020.11.14提高组模拟】鬼渊传说
题目 Time Limits: 1000 ms Memory Limits: 518400 KB 简要题意 给出一个网格图,每个格子有黑白二色,求有多少个子矩形满足将其挖出来后恰好有一个黑色四连通块且 ...
- 【2020.12.03提高组模拟】袋鼠
题目 题目描述 你知道吗?乌拉圭的人口有345.7万,同时,仅澳大利亚就有4700万只袋鼠. 袋鼠决定入侵乌拉圭.袋鼠们将在平原上布阵,平原被划分成 n×mn \times mn×m 的网格. 每个格 ...
- 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 ...
- 提高组模拟试题七第二试 佐佐小次郎
提高组模拟试题七第二试 佐佐小次郎 Time Limit:10000MS Memory Limit:65536K Total Submit:26 Accepted:26 Case Time Limi ...
- 第一届『Citric杯』NOIP提高组模拟赛 题解
[官方题解]第一届『Citric杯』NOIP提高组模拟赛 题解 第一题 柠檬超市 这题是本次模拟赛的送分题.做法显然. 但是注意此题有一个陷阱: 注意W和C的规模都是10^9,所以如果直接用doubl ...
最新文章
- hdu 4937 Lucky Number(数学题 进制转换)2014多校训练第7场
- C语言链表的来源分析
- python 什么是原类_Python 什么是元类(metaclasses)?
- 细数改善WPF应用程序性能的10大方法
- 与0xf2值相等的是python_腾讯笔试题涵盖的基础知识
- 电脑时间校对器_笔记本电脑如何保养?华为教你五招轻松延长使用时间
- confirm + if 逻辑判断 -代码篇
- .5-浅析webpack源码之入口函数
- 数据交换-电路/报文/分组交换
- Intel的AVX2指令集解读
- Linq To EF (添加记录后获取添加的自增ID和叫“ID”的列不是自增列不让插入的问题)...
- 数据结构课程设计(基于AVL树的身份证管理系统)
- 中端存储和高端存储的区别
- iPhone手机ipa破解补丁安装方法和ipa软件游戏安装教程(1)
- 动态DNS的定义以及优缺点有哪些
- 初学者学习插画原画以后就业方向有哪些?和大家聊聊插画原画师就业、薪资等
- 积分竟然比微分早了1300年!一文讲清积分的历史
- 渡一教育公开课web前端开发JavaScript精英课学习笔记(二十九)JavaScript 骇客帝国
- Win2003集群简介
- 3.Spark的安装(华为云学习笔记,Spark编程基础,大数据)
热门文章
- Buzzer Speaker
- 同时登录多个飞信客户端的方法
- Tshock的config.json配置文件翻译(对应5.1.2版本)
- 统计学生平均成绩。使用静态成员函数。如果不将average函数定义为静态成员函数行不行?程序能否通过编译?需要作什么修改?为什么要用静态成员函数?请分析其理由。
- python求三个数平均值_Python操作Excel教程-average函数求平均值
- 推荐开源矢量绘图软件Inkscape
- 市盈率仍是判断股市泡沫的重要标准
- Android版Office App,微软office android app
- Bezier曲线切割
- 16. DICOM图像显示-DCMTK-cda转dicom