[关闭]
@xiaoziyao 2020-11-15T02:41:23.000000Z 字数 2429 阅读 874

CF342E Xenia and Tree解题报告

解题报告


CF342E Xenia and Tree解题报告:

更好的阅读体验

吐槽:好奇怪呀,为什么交了两份相同的代码一份AC一份WA,不应该返回相同的答案吗。

题意

分析

操作分块。

我们设定一个阈值,对操作序列每个操作分一块。

对于每一次询问,我们对红点分类讨论:

具体地,每跨越一次块,我们就把这个块内所有的红点bfs一遍,更新它们到所有点的距离,这是的,但是由于只会跨越次块,所以总复杂度为

对于在这个块内的红点,我们枚举它们,然后用ST表的的lca求距离,这样我们的复杂度为,总复杂度为

故时间复杂度为:,很显然时复杂度较优,为

代码

分块常数小,加了个快读就到最优解了。

  1. #include<stdio.h>
  2. #include<math.h>
  3. #define inf 1000000000
  4. const int maxn=100005,maxm=200005,maxk=20,maxt=405,maxq=100005;
  5. int n,m,e,qs,t,now;
  6. int start[maxn],to[maxm],then[maxm],lg[maxn<<1],ST[maxn<<1][maxk],dep[maxn],in[maxn],bl[maxt],br[maxt],opt[maxq],k[maxq],dis[maxn],q[maxn];
  7. inline int min(int a,int b){
  8. return a<b? a:b;
  9. }
  10. inline int calc(int a,int b){
  11. return dep[a]<dep[b]? a:b;
  12. }
  13. inline void swp(int &a,int &b){
  14. a+=b,b=a-b,a-=b;
  15. }
  16. inline void add(int x,int y){
  17. then[++e]=start[x],start[x]=e,to[e]=y;
  18. }
  19. void dfs(int x,int last){
  20. dep[x]=dep[last]+1,in[x]=++qs,ST[qs][0]=x;
  21. for(int i=start[x];i;i=then[i]){
  22. int y=to[i];
  23. if(y==last)
  24. continue;
  25. dfs(y,x);
  26. ST[++qs][0]=x;
  27. }
  28. }
  29. void getST(){
  30. lg[0]=-1;
  31. for(int i=1;i<=qs;i++)
  32. lg[i]=lg[i/2]+1;
  33. for(int i=1;i<=18;i++)
  34. for(int j=1;j+(1<<i)-1<=qs;j++)
  35. ST[j][i]=calc(ST[j][i-1],ST[j+(1<<(i-1))][i-1]);
  36. }
  37. int lca(int a,int b){
  38. if(in[a]>in[b])
  39. swp(a,b);
  40. int l=in[a],r=in[b],k=lg[r-l+1];
  41. return calc(ST[l][k],ST[r-(1<<k)+1][k]);
  42. }
  43. int getdis(int a,int b){
  44. int c=lca(a,b);
  45. return dep[a]+dep[b]-2*dep[c];
  46. }
  47. void bfs(int a,int b){
  48. qs=0;
  49. if(a==-1)
  50. q[++qs]=1;
  51. else for(int i=a;i<=b;i++)
  52. if(opt[i]==1)
  53. q[++qs]=k[i];
  54. int now=1;
  55. while(now<=qs){
  56. int x=q[now];
  57. now++;
  58. for(int i=start[x];i;i=then[i]){
  59. int y=to[i];
  60. if(dis[y]<=dis[x]+1)
  61. continue;
  62. dis[y]=dis[x]+1,q[++qs]=y;
  63. }
  64. }
  65. }
  66. int query(int x,int a,int b){
  67. int res=dis[x];
  68. for(int i=a;i<=b;i++)
  69. if(opt[i]==1)
  70. res=min(res,getdis(x,k[i]));
  71. return res;
  72. }
  73. void read(int &x){
  74. char c=getchar();
  75. x=0;
  76. for(;c<'0'||c>'9';c=getchar());
  77. for(;c>='0'&&c<='9';c=getchar())
  78. x=x*10+c-48;
  79. }
  80. int main(){
  81. read(n),read(m);
  82. for(int i=1;i<n;i++){
  83. int x,y;
  84. read(x),read(y);
  85. add(x,y),add(y,x);
  86. }
  87. dfs(1,0),getST();
  88. t=sqrt(m);
  89. for(int i=1;i<=t;i++)
  90. bl[i]=br[i-1]+1,br[i]=i*t;
  91. if(br[t]<m)
  92. t++,bl[t]=bl[t-1]+1,br[t]=m;
  93. for(int i=1;i<=n;i++)
  94. dis[i]=inf;
  95. int last=1;
  96. dis[1]=0,bfs(-1,-1);
  97. for(int i=1;i<=m;i++){
  98. if(i>br[last])
  99. bfs(bl[last],br[last]),last++;
  100. read(opt[i]),read(k[i]);
  101. if(opt[i]==1)
  102. dis[k[i]]=0;
  103. if(opt[i]==2)
  104. printf("%d\n",query(k[i],bl[last],i));
  105. }
  106. return 0;
  107. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注