P4175 [CTSC2008]网络管理

题目描述

带修改树上链的第\(k\)大

输入输出格式

输入格式:

第一行为两个整数\(N\)和\(Q\),分别表示路由器总数和询问的总数。

第二行有\(N\)个整数,第\(i\)个数表示编号为\(i\)的路由器初始的数据延迟时间\(T_i\)。

紧接着\(N-1\)行,每行包含两个整数\(x\)和\(y\)。表示有一条光缆连接路由器\(x\)和路由器\(y\)。

紧接着是\(Q\)行,每行三个整数\(k\)、\(a\)、\(b\)。

如果\(k=0\),则表示路由器\(a\)的状态发生了变化,它的数据交换延迟时间由\(T_a\)变为\(b\)。

如果\(k>0\),则表示询问\(a\)到\(b\)的路径上所经过的所有路由器(包括\(a\)和\(b\))中延迟第\(k\)大的路由器的延迟时间。注意\(a\)可以等于\(b\),此时路径上只有一个路由器。

输出格式:

对于每一个第二种询问(\(k>0\)),输出一行。包含一个整数为相应的延迟时间。如果路径上的路由器不足\(k\)个,则输出信息“\(\tt{invalid request!}\)”(全部小写不包含引号,两个单词之间有一个空格)。

说明

测试数据满足\(N,Q\le 80000\),任意一个路由器在任何时刻都满足延迟时间小于\(10^8\)。

对于所有询问满足\(0\le K\le N\) 。


写了两种分别是\(O((N+Q)\log^2N\log10^8)\)和\(O((N+Q)\log N\log10^8)\)的

谁知道前面的跑得快一些...


三个\(\log\)的思路是 整体二分+树链剖分+树状数组

其实就是在普通的整体二分的基础上加了个树链剖分用来维护链。

思路比较简单。

Code:

  1. #include <cstdio>
  2. #include <cctype>
  3. const int N=240010;
  4. int head[N],to[N],Next[N],cnt;
  5. void add(int u,int v)
  6. {
  7. to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
  8. }
  9. struct node{int op,x,y,k;}q[N],ql[N],qr[N];
  10. int n,m,Q,qu,ans[N],poi[N];
  11. int read()
  12. {
  13. int x=0;char c=getchar();
  14. while(!isdigit(c)) c=getchar();
  15. while(isdigit(c)){x=x*10+c-'0';c=getchar();}
  16. return x;
  17. }
  18. int dfn[N],top[N],f[N],dep[N],ws[N],siz[N],dfsclock;
  19. void dfs1(int now)
  20. {
  21. siz[now]=1;
  22. for(int i=head[now];i;i=Next[i])
  23. {
  24. int v=to[i];
  25. if(v==f[now]) continue;
  26. f[v]=now;
  27. dep[v]=dep[now]+1;
  28. dfs1(v);
  29. siz[now]+=siz[v];
  30. if(siz[ws[now]]<siz[v]) ws[now]=v;
  31. }
  32. }
  33. void dfs2(int now,int anc)
  34. {
  35. dfn[now]=++dfsclock;
  36. top[now]=anc;
  37. if(ws[now]) dfs2(ws[now],anc);
  38. for(int i=head[now];i;i=Next[i])
  39. if(!dfn[to[i]])
  40. dfs2(to[i],to[i]);
  41. }
  42. int LCA(int x,int y)
  43. {
  44. while(top[x]!=top[y])
  45. {
  46. if(dep[top[x]]>=dep[top[y]])
  47. x=f[top[x]];
  48. else
  49. y=f[top[y]];
  50. }
  51. return dep[x]<dep[y]?x:y;
  52. }
  53. int S[N],tmp;
  54. void Swap(int &x,int &y){tmp=x,x=y,y=tmp;}
  55. void change(int x,int d){while(x<=n)S[x]+=d,x+=x&-x;}
  56. int ask(int x){int sum=0;while(x)sum+=S[x],x-=x&-x;return sum;}
  57. int query(int x,int y)
  58. {
  59. int sum=0;
  60. while(top[x]!=top[y])
  61. {
  62. if(dep[top[x]]>=dep[top[y]])
  63. {
  64. sum+=ask(dfn[x])-ask(dfn[top[x]]-1);
  65. x=f[top[x]];
  66. }
  67. else
  68. {
  69. sum+=ask(dfn[y])-ask(dfn[top[y]]-1);
  70. y=f[top[y]];
  71. }
  72. }
  73. if(dep[x]<dep[y]) Swap(x,y);
  74. sum+=ask(dfn[x])-ask(dfn[y]-1);
  75. return sum;
  76. }
  77. #define rep(i,a,b) for(int i=a;i<=b;i++)
  78. void divide(int l,int r,int s,int t)
  79. {
  80. if(s>t)return;
  81. if(l==r){rep(i,s,t)ans[q[i].op]=l;return;}
  82. int mid=l+r>>1,lp=0,rp=0;
  83. rep(i,s,t)
  84. {
  85. if(q[i].op)
  86. {
  87. int c=query(q[i].x,q[i].y);
  88. if(q[i].k<=c) qr[++rp]=q[i];
  89. else ql[++lp]=q[i],ql[lp].k-=c;
  90. }
  91. else
  92. {
  93. if(q[i].x>mid) change(dfn[q[i].y],q[i].k),qr[++rp]=q[i];
  94. else ql[++lp]=q[i];
  95. }
  96. }
  97. rep(i,s,t) if(!q[i].op&&q[i].x>mid) change(dfn[q[i].y],-q[i].k);
  98. rep(i,s,s+lp-1) q[i]=ql[i+1-s];
  99. rep(i,s+lp,t) q[i]=qr[i+1-s-lp];
  100. divide(l,mid,s,s+lp-1),divide(mid+1,r,s+lp,t);
  101. }
  102. int main()
  103. {
  104. m=n=read(),Q=read();
  105. rep(i,1,n) poi[i]=q[i].x=read(),q[i].y=i,q[i].k=1;
  106. int u,v;rep(i,1,(n-1)) u=read(),v=read(),add(u,v),add(v,u);
  107. dep[1]=1;
  108. dfs1(1),dfs2(1,1);
  109. rep(i,1,Q)
  110. {
  111. ++m;
  112. q[m].op=read();
  113. if(q[m].op)
  114. {
  115. q[m].x=read(),q[m].y=read(),q[m].k=q[m].op,q[m].op=++qu;
  116. int lca=LCA(q[m].x,q[m].y);
  117. if(dep[q[m].x]+dep[q[m].y]-dep[lca]-dep[f[lca]]<q[m].k) ans[qu]=-1,--m;
  118. }
  119. else
  120. {
  121. int p=read();
  122. q[m].x=poi[p],q[m].y=p,q[m].k=-1;
  123. ++m;
  124. poi[p]=q[m].x=read(),q[m].y=p,q[m].k=1;
  125. }
  126. }
  127. divide(0,(int)(1e8),1,m);
  128. rep(i,1,qu) if(~ans[i]) printf("%d\n",ans[i]);else puts("invalid request!");
  129. return 0;
  130. }

两个\(\log\)的思路就是树状数组套权值线段树了。

对于查询一条\(u\)到根的链,我们可以理解为每个\(u\)到根的路径上的点都做了贡献,我们可以事先把贡献都放到\(u\)上,然后直接查询\(u\)就可以了。而一个点可以对也仅对\(\tt{Ta}\)每个子树的点产生一个贡献,这段子树在\(dfs\)序上是连续的。

在信息可加减的情况下,查询任意的链只需要两个端点的信息减去它们LCA初即LCA处父亲的信息即可。

考虑每个点维护一个权值线段树的话,是不容易维护区间信息的。不妨借助差分的思想,就可以转换成维护单点修改和区间查询了。

直接在权值线段树的外层套树状数组,然后每次查询时在树上二分即可。

Code:

  1. #include <cstdio>
  2. #include <cctype>
  3. const int N=8e4+10;
  4. const int inf=1e8;
  5. int read()
  6. {
  7. int x=0;char c=getchar();
  8. while(!isdigit(c)) c=getchar();
  9. while(isdigit(c)) {x=x*10+c-'0';c=getchar();}
  10. return x;
  11. }
  12. int n,Q,poi[N];
  13. int head[N],to[N<<1],Next[N<<1],cnt;
  14. void add(int u,int v)
  15. {
  16. to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
  17. to[++cnt]=u,Next[cnt]=head[v],head[v]=cnt;
  18. }
  19. int f[N][20],dep[N],low[N],dfn[N],dfsclock;
  20. void dfs(int now)
  21. {
  22. dfn[now]=++dfsclock;
  23. for(int i=1;f[now][i-1];i++) f[now][i]=f[f[now][i-1]][i-1];
  24. for(int i=head[now];i;i=Next[i])
  25. {
  26. int v=to[i];
  27. if(v==f[now][0]) continue;
  28. dep[v]=dep[now]+1;
  29. f[v][0]=now;
  30. dfs(v);
  31. }
  32. low[now]=dfsclock;
  33. }
  34. int LCA(int x,int y)
  35. {
  36. if(dep[x]<dep[y]) return LCA(y,x);
  37. for(int i=18;~i;i--)
  38. if(dep[f[x][i]]>=dep[y])
  39. x=f[x][i];
  40. if(x==y) return x;
  41. for(int i=18;~i;i--)
  42. if(f[x][i]!=f[y][i])
  43. x=f[x][i],y=f[y][i];
  44. return f[x][0];
  45. }
  46. #define ls ch[now][0]
  47. #define rs ch[now][1]
  48. int ch[N*200][2],sum[N*200],tot,root[N];
  49. void change(int &now,int l,int r,int p,int d)
  50. {
  51. if(!now) now=++tot;
  52. if(l==r) {sum[now]+=d;return;}
  53. int mid=l+r>>1;
  54. if(p<=mid) change(ls,l,mid,p,d);
  55. else change(rs,mid+1,r,p,d);
  56. sum[now]=sum[ls]+sum[rs];
  57. }
  58. #define rep(i,a,b) for(int i=a;i<=b;i++)
  59. void modify(int x,int loc,int d){while(x<=n)change(root[x],1,inf,loc,d),x+=x&-x;}
  60. int sa[20],sb[20],sc[20],sd[20];
  61. int query(int a,int b,int c,int d,int k)
  62. {
  63. sa[0]=sb[0]=sc[0]=sd[0]=0;
  64. for(int i=a;i;i-=i&-i) sa[++sa[0]]=root[i];
  65. for(int i=b;i;i-=i&-i) sb[++sb[0]]=root[i];
  66. for(int i=c;i;i-=i&-i) sc[++sc[0]]=root[i];
  67. for(int i=d;i;i-=i&-i) sd[++sd[0]]=root[i];
  68. int l=1,r=inf;
  69. while(l<r)
  70. {
  71. int mid=l+r>>1,c=0;
  72. for(int i=1;i<=sa[0];i++) c+=sum[ch[sa[i]][1]];
  73. for(int i=1;i<=sb[0];i++) c+=sum[ch[sb[i]][1]];
  74. for(int i=1;i<=sc[0];i++) c-=sum[ch[sc[i]][1]];
  75. for(int i=1;i<=sd[0];i++) c-=sum[ch[sd[i]][1]];
  76. if(c>=k)
  77. {
  78. for(int i=1;i<=sa[0];i++) sa[i]=ch[sa[i]][1];
  79. for(int i=1;i<=sb[0];i++) sb[i]=ch[sb[i]][1];
  80. for(int i=1;i<=sc[0];i++) sc[i]=ch[sc[i]][1];
  81. for(int i=1;i<=sd[0];i++) sd[i]=ch[sd[i]][1];
  82. l=mid+1;
  83. }
  84. else
  85. {
  86. for(int i=1;i<=sa[0];i++) sa[i]=ch[sa[i]][0];
  87. for(int i=1;i<=sb[0];i++) sb[i]=ch[sb[i]][0];
  88. for(int i=1;i<=sc[0];i++) sc[i]=ch[sc[i]][0];
  89. for(int i=1;i<=sd[0];i++) sd[i]=ch[sd[i]][0];
  90. k-=c,r=mid;
  91. }
  92. }
  93. return l;
  94. }
  95. int main()
  96. {
  97. n=read(),Q=read();
  98. rep(i,1,n) poi[i]=read();
  99. rep(i,1,(n-1)) add(read(),read());
  100. dep[1]=1;dfs(1);
  101. rep(i,1,n)
  102. modify(dfn[i],poi[i],1),modify(low[i]+1,poi[i],-1);
  103. rep(i,1,Q)
  104. {
  105. int op=read();
  106. if(op)
  107. {
  108. int u=read(),v=read();
  109. int lca=LCA(u,v);
  110. if(dep[u]+dep[v]-dep[lca]-dep[f[lca][0]]<op) puts("invalid request!");
  111. else printf("%d\n",query(dfn[u],dfn[v],dfn[lca],dfn[f[lca][0]],op));
  112. }
  113. else
  114. {
  115. int p=read();
  116. modify(dfn[p],poi[p],-1),modify(low[p]+1,poi[p],1);
  117. poi[p]=read();
  118. modify(dfn[p],poi[p],1),modify(low[p]+1,poi[p],-1);
  119. }
  120. }
  121. return 0;
  122. }

2018.11.3

洛谷 P4175 [CTSC2008]网络管理 解题报告的更多相关文章

  1. 洛谷P4175 - [CTSC2008]网络管理

    Portal Description 给出一棵\(n(n\leq8\times10^4)\)个点的带点权的树,进行\(m(m\leq8\times10^4)\)次操作,操作有两种: 修改一个点的点权. ...

  2. 洛谷 P1783 海滩防御 解题报告

    P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...

  3. 洛谷 P4597 序列sequence 解题报告

    P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...

  4. 洛谷1087 FBI树 解题报告

    洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...

  5. 洛谷 P3349 [ZJOI2016]小星星 解题报告

    P3349 [ZJOI2016]小星星 题目描述 小\(Y\)是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有\(n\)颗小星星,用\(m\)条彩色的细线串了起来,每条细线连着两颗小星星. 有一 ...

  6. 洛谷 P3177 树上染色 解题报告

    P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色, ...

  7. 洛谷 P4705 玩游戏 解题报告

    P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...

  8. 洛谷 P1272 重建道路 解题报告

    P1272 重建道路 题目描述 一场可怕的地震后,人们用\(N\)个牲口棚\((1≤N≤150\),编号\(1..N\))重建了农夫\(John\)的牧场.由于人们没有时间建设多余的道路,所以现在从一 ...

  9. 洛谷 [HNOI2014]道路堵塞 解题报告

    [HNOI2014]道路堵塞 题意 给一个有向图并给出一个这个图的一个\(1\sim n\)最短路,求删去这条最短路上任何一条边后的最短路. 又事SPFA玄学... 有个结论,新的最短路一定是\(1\ ...

随机推荐

  1. 原生js常用方法

    原生JavaScript设置cookie值 function setCookie(name, value, Hours) { var d = new Date(); var offset = 8; v ...

  2. 孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9并使用pydocx模块将结果写入word文档

    孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 到今天终于完成了对docx模块针对 ...

  3. java扫描控制台输入

    由于因最近练习算法的需要,加上API文档中翻译的太过模糊,做了一些小测试,算是武断的记下一些个人结论. Scanner cin = new Scanner(System.in); 对于cin.next ...

  4. 常用正则表达式,你要的都在这里(校验字符,数字,特殊需求qq,电话等)

    一.校验数字的表达式 1 数字:^[0-9]*$ 2 n位的数字:^\d{n}$ 3 至少n位的数字:^\d{n,}$ 4 m-n位的数字:^\d{m,n}$ 5 零和非零开头的数字:^(0|[1-9 ...

  5. HDU 4308 Saving Princess claire_(简单BFS)

    求出不使用P点时起点到终点的最短距离,求出起点到所有P点的最短距离,求出终点到所有P点的最短距离. 答案=min( 不使用P点时起点到终点的最短距离, 起点到P的最短距离+终点到P的最短距离 ) #i ...

  6. dataTables工作总结

    近期在工作中用到了dataTables,现在总结一下在工作中遇到的问题以及解决方法,如有不妥之处希望多多指教,定会改进. 首先这里用的是coloradmin框架,在vs环境下开发. 这里写一个容器用于 ...

  7. win8安装Ubuntu14

    概述: 1.复制安装镜像和启动文件到FAT32分区 2.查找出FAT32分区的分区号,修改启动配置文件 3.启动FAT32分区的安装镜像,开始安装 UEFI Win7/8/Ubuntu 硬盘安装Ubu ...

  8. ACM 第十三天

    训练赛题目 题目地址:https://odzkskevi.qnssl.com/415c275cb0a15fcb4ede21b8cb5297de?v=1533963116   A题代码: #includ ...

  9. C# 创建Excel或需不安装Office

    第一种.Aspose.Cells.dll //如果需要饶过office Excel那么就看我最后的实现方法吧~! //我最后的实现是使用的第三方Aspose.Cells.dll //具了解这个dll一 ...

  10. ZOJ 1913 J-Eucild's Game

    https://vjudge.net/contest/67836#problem/J Two players, Stan and Ollie, play, starting with two natu ...