【BZOJ4009】[HNOI2015]接水果

Description

风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果。由于她已经DT FC 了The big black,  她觉得这个游戏太简单了,于是发明了一个更加难的版本。首先有一个地图,是一棵由 n 个顶点、n-1 条边组成的树(例如图 1给出的树包含 8 个顶点、7 条边)。这颗树上有 P 个盘子,每个盘子实际上是一条路径(例如图 1 中顶点 6 到顶点 8 的路径),并且每个盘子还有一个权值。第 i 个盘子就是顶点a_i到顶点b_i的路径(由于是树,所以从a_i到b_i的路径是唯一的),权值为c_i。接下来依次会有Q个水果掉下来,每个水果本质上也是一条路径,第i 个水果是从顶点 u_i 到顶点v_i 的路径。幽香每次需要选择一个盘子去接当前的水果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径(例如图1中从 3到7 的路径是从1到8的路径的子路径)。这里规定:从a 到b的路径与从b到 a的路径是同一条路径。当然为了提高难度,对于第 i 个水果,你需要选择能接住它的所有盘子中,权值第 k_i 小的那个盘子,每个盘子可重复使用(没有使用次数的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗? 

Input

第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数。

接下来n-1 行,每行两个数 a、b,表示树上的a和b 之间有一条边。树中顶点
按1到 n标号。 接下来 P 行,每行三个数 a、b、c,表示路径为 a 到 b、权值为 c 的盘子,其中0≤c≤10^9,a不等于b。 
接下来Q行,每行三个数 u、v、k,表示路径为 u到 v的水果,其中 u不等于v,你需要选择第 k小的盘子,第k 小一定存在。 

Output

对于每个果子,输出一行表示选择的盘子的权值。

Sample Input

10 10 10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
3 2 217394434
10 7 13022269
6 7 283254485
6 8 333042360
4 6 442139372
8 3 225045590
10 4 922205209
10 8 808296330
9 2 486331361
4 9 551176338
1 8 5
3 8 3
3 8 4
1 8 3
4 8 1
2 3 1
2 3 1
2 3 1
2 4 1
1 4 1

Sample Output

442139372
333042360
442139372
283254485
283254485
217394434
217394434
217394434
217394434
217394434

HINT

N,P,Q<=40000。

题解:觉得很熟悉?赶紧去复习精神污染吧!

设入栈序p,出栈序q,那么a-b是x-y的子路径有以下两种情况(p[a]<p[b],p[x]<p[y])。

a是b的祖先,那么设b在a的c儿子的子树中,则有1<=p[x]<p[c],q[c]<p[y]<=n。
a不是b的祖先,则有p[a]<=p[x]<=q[a],p[b]<=p[y]<=q[b]。

这就变成了平面上有一堆矩形,每个矩形都有一个权值,每次询问一个点,问在所有包含这个点的矩形中,权值第k小的权值是多少。可以用树套树做,当然,用整体二分+扫描线+树状数组区间修改也是极好的啦~

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <algorithm>
  5. using namespace std;
  6. const int maxn=40010;
  7. int n,tot,tp,m1,m2,cnt,now;
  8. int to[maxn<<1],next[maxn<<1],head[maxn],p1[maxn],p2[maxn],fa[16][maxn],dep[maxn],ans[maxn],s[maxn],vis[maxn];
  9. struct operation
  10. {
  11. int a1,b1,a2,b2,v;
  12. operation() {}
  13. operation(int _1,int _2,int _3,int _4,int _5) {a1=_1,b1=_2,a2=_3,b2=_4,v=_5;}
  14. }p[maxn<<1];
  15. struct ask
  16. {
  17. int a,b,v,sl,org;
  18. ask() {}
  19. ask(int _1,int _2,int _3,int _4) {a=_1,b=_2,v=_3,org=_4;}
  20. }q[maxn],qq[maxn];
  21. struct node
  22. {
  23. int x,a,b,v;
  24. node() {}
  25. node(int _1,int _2,int _3,int _4) {x=_1,a=_2,b=_3,v=_4;}
  26. }pp[maxn<<1];
  27. inline int rd()
  28. {
  29. int ret=0,f=1; char gc=getchar();
  30. while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
  31. while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
  32. return ret*f;
  33. }
  34. void add(int a,int b)
  35. {
  36. to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
  37. }
  38. void dfs(int x)
  39. {
  40. p1[x]=++p1[0];
  41. for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[0][x]) fa[0][to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
  42. p2[x]=p1[0];
  43. }
  44. void updata(int x,int v)
  45. {
  46. for(int i=x;i<=n;i+=i&-i)
  47. {
  48. if(vis[i]<now) vis[i]=now,s[i]=0;
  49. s[i]+=v;
  50. }
  51. }
  52. int query(int x)
  53. {
  54. int i,ret=0;
  55. for(i=x;i;i-=i&-i)
  56. {
  57. if(vis[i]<now) vis[i]=now,s[i]=0;
  58. ret+=s[i];
  59. }
  60. return ret;
  61. }
  62. bool cmpx(node a,node b)
  63. {
  64. return a.x<b.x;
  65. }
  66. bool cmpa(ask a,ask b)
  67. {
  68. return a.a<b.a;
  69. }
  70. bool cmpv(operation a,operation b)
  71. {
  72. return a.v<b.v;
  73. }
  74. void solve(int l,int r,int L,int R)
  75. {
  76. if(l==r||L>R)
  77. {
  78. for(int i=L;i<=R;i++) ans[q[i].org]=p[l].v;
  79. return ;
  80. }
  81. sort(p+l,p+r+1,cmpv);
  82. int mid=(l+r)>>1,MID=L-1,i,j;
  83. for(tp=0,now++,i=l;i<=mid;i++)
  84. pp[++tp]=node(p[i].a1,p[i].a2,p[i].b2,1),pp[++tp]=node(p[i].b1+1,p[i].a2,p[i].b2,-1);
  85. sort(pp+1,pp+tp+1,cmpx),sort(q+L,q+R+1,cmpa);
  86. for(i=L,j=1;i<=R;i++)
  87. {
  88. for(;j<=tp&&pp[j].x<=q[i].a;j++) updata(pp[j].a,pp[j].v),updata(pp[j].b+1,-pp[j].v);
  89. q[i].sl=query(q[i].b),MID+=(q[i].sl>=q[i].v);
  90. }
  91. int h1=L,h2=MID+1;
  92. for(i=L;i<=R;i++)
  93. {
  94. if(q[i].sl>=q[i].v) qq[h1++]=q[i];
  95. else q[i].v-=q[i].sl,qq[h2++]=q[i];
  96. }
  97. for(i=L;i<=R;i++) q[i]=qq[i];
  98. solve(l,mid,L,MID),solve(mid+1,r,MID+1,R);
  99. }
  100. int FA(int x,int y)
  101. {
  102. for(int j=15;j>=0;j--) if((1<<j)<=y) y-=(1<<j),x=fa[j][x];
  103. return x;
  104. }
  105. int main()
  106. {
  107. //freopen("bz4009.in","r",stdin);
  108. n=rd(),m1=rd(),m2=rd();
  109. int i,j,a,b,c,d;
  110. memset(head,-1,sizeof(head));
  111. for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
  112. dep[1]=1,dfs(1);
  113. for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) fa[j][i]=fa[j-1][fa[j-1][i]];
  114. for(i=1;i<=m1;i++)
  115. {
  116. a=rd(),b=rd(),c=rd();
  117. if(p1[a]>p1[b]) swap(a,b);
  118. if(p2[a]>=p2[b])
  119. {
  120. d=FA(b,dep[b]-dep[a]-1);
  121. p[++tot]=operation(1,p1[d]-1,p1[b],p2[b],c);
  122. if(p2[b]<n) p[++tot]=operation(p1[b],p2[b],p2[d]+1,n,c);
  123. }
  124. else p[++tot]=operation(p1[a],p2[a],p1[b],p2[b],c);
  125. }
  126. for(i=1;i<=m2;i++)
  127. {
  128. a=rd(),b=rd();
  129. if(p1[a]>p1[b]) swap(a,b);
  130. q[i]=ask(p1[a],p1[b],rd(),i);
  131. }
  132. solve(1,tot,1,m2);
  133. for(i=1;i<=m2;i++) printf("%d\n",ans[i]);
  134. return 0;
  135. }//4 4 1 1 2 2 3 1 4 1 2 2 2 3 3 1 4 4 4 1 1 2 4 1

【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组的更多相关文章

  1. BZOJ 4009: [HNOI2015]接水果 (整体二分+扫描线 树状数组)

    整体二分+扫描线 树状数组 具体做法看这里a CODE #include <cctype> #include <cstdio> #include <cstring> ...

  2. bzoj4009 [HNOI2015]接水果 整体二分+扫描线+树状数组+dfs序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4009 题解 考虑怎样的情况就会有一个链覆盖另一个链. 设被覆盖的链为 \(a - b\),覆盖 ...

  3. Luogu3527 POI2011 Meteors 整体二分、树状数组、差分

    传送门 比较板子的整体二分题目,时限有点紧注意常数 整体二分的过程中将时间在\([l,mid]\)之间的流星使用树状数组+差分进行维护,然后对所有国家查看一遍并分好类,递归下去,记得消除答案在\([m ...

  4. [bzoj2527][Poi2011]Meteors_整体二分_树状数组

    Meteors bzoj-2527 Poi-2011 题目大意:题目链接. 注释:略. 想法: 首先答案可以离线,且具有单调性. 这里的单调性就是随着时间的推移,每个国家收集的陨石数增加. 不难想到整 ...

  5. [bzoj2738]矩阵乘法_整体二分_树状数组

    矩阵乘法 bzoj-2738 题目大意:给定一个$n*n$的矩阵.每次给定一个矩阵求矩阵$k$小值. 注释:$1\le n\le 500$,$1\le q\le 6\cdot 10^4$. 想法: 新 ...

  6. [POI2011]MET-Meteors 整体二分_树状数组_卡常

    线段树肯定会 TLE 的,必须要用树状数组. Code: // luogu-judger-enable-o2 #include <cstdio> #include <algorith ...

  7. [luogu4479][BJWC2018]第k大斜率【二维偏序+二分+离散化+树状数组】

    传送门 https://www.luogu.org/problemnew/show/P4479 题目描述 在平面直角坐标系上,有 n 个不同的点.任意两个不同的点确定了一条直线.请求出所有斜率存在的直 ...

  8. 【bzoj4009】[HNOI2015]接水果 DFS序+树上倍增+整体二分+树状数组

    题目描述 给出一棵n个点的树,给定m条路径,每条路径有一个权值.q次询问求一个路径包含的所有给定路径中权值第k小的. 输入 第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数. 接下来n ...

  9. Codeforces 899 F. Letters Removing (二分、树状数组)

    题目链接:Letters Removing 题意: 给你一个长度为n的字符串,给出m次操作.每次操作给出一个l,r和一个字符c,要求删除字符串l到r之间所有的c. 题解: 看样例可以看出,这题最大的难 ...

随机推荐

  1. ASP.NET MVC学习---(九)权限过滤机制(完结篇)

    相信对权限过滤大家伙都不陌生 用户要访问一个页面时 先对其权限进行判断并进行相应的处理动作 在webform中 最直接也是最原始的办法就是 在page_load事件中所有代码之前 先执行一个权限判断的 ...

  2. Android学习(二十二)ContentMenu上下文菜单

    一.上下问菜单 在某个菜单项上长按,会弹出一个菜单,这个就是上下文菜单.有点类似与Windows系统中的右键菜单. 二.上下文菜单的内容 1.标题 2.图标 3.菜单项 4.对应的菜单事件 三.Opt ...

  3. VB断点调试

    最近都在敲机房收费系统,这个系统是我们第一次自己在没有源代码的情况下进行的系统. 写程序的时候逻辑非常重要,可是我们还要清楚非常多时候你以为的并非你以为的! 就像在敲机房的时候,我们明明理清了逻辑.并 ...

  4. LeetCode-Minimum Window Substring -- 窗口问题

    题目描述 Given a string S and a string T, find the minimum window in S which will contain all the charac ...

  5. Maven 缺省内置变量

    1.${project.build.directory} 构建目录,缺省为target 2.${project.build.outputDirectory} 构建过程输出目录,缺省为target/cl ...

  6. 编辑器未包含main类型

    明明写了main函数,在运行的时候,却得到这样的结果. 解决方案: 重新建立一个项目,建立项目的过程中

  7. NB的CSS样式集锦1——CSS3滚动条美化,CSS3滚动条皮肤

    转自:http://www.pengyaou.com/codecss3/POKDNMS_112.html CSS3 -webkit-scrollbar滚动条皮肤美化实现,利用-webkit-scrol ...

  8. delphi的字节对齐

    如果不改编译选项Delphi的Record默认也是4字节对齐的. 可以用编译开关指定 {$A4+}就是4字节对齐.同理{$A2+}.{$A1+}等.{$A1+}等同于Packed Record 主要容 ...

  9. Delphi中array of const应用

    Delphi的Format函数大家都用得很多,第二个参数用着确实很方便.最近在数据库开发应用中需要自己创建一个带array of const参数的函数,对于常用的类型String,Integer,Po ...

  10. matlab-非线性方程求根函数及函数曲线绘制

    Matlab中提供了很多求解非线性方程(y=f(x))的函数,刚開始使用,真的很困惑.全部.这里依据matlab的help文档对这些函数做一些小小的总结 fsolve函数 用来求解非线性方程组:F(x ...