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。

Source

Solution

本题简化题意:n个结点的树,给定m条带权值的路径(端点不重合),q个询问,每个询问给定一条路径,查询m条路径中所有它的子路径的权值第k小。

首先如果两个路径有包含关系,那么是可以用dfs序的区间表示的,具体看代码,所以我们可以把集合中的两个dfs序区间看成二维平面上的一个矩形,然后询问看成一个点,这样题意就转化成了包含一个点的矩形中权值第k大的,然后我们二分答案,就成了判定性问题,判断够不够k个,这样就可以直接用扫描线做啦。然后二分的话复杂度爆炸,所以要整体二分,在整体二分时候的细节见代码,用树状数组+排序就可以解决二维数点问题。

Code

  1. #include <bits/stdc++.h>
  2. #define N 40005
  3. using namespace std;
  4. struct nod
  5. {
  6. int x,y,z,v,w;
  7. nod(int a=0,int b=0,int c=0,int d=0,int e=0){x=a,y=b,z=c,v=d,w=e;}
  8. bool operator<(const nod &a)const{return x<a.x;}
  9. }a[N*3],q[N*2],t[N*2];
  10. int n,m,k,x,y,z,g,he[N],to[N<<1],ne[N<<1],cnt,anc[N][20],dep[N],in[N],ou[N],I,tot,f[N],val[N],vl[N],ans[N];
  11. bool cmp(nod a,nod b){return a.v<b.v;}
  12. void add(int x,int y){to[++cnt]=y,ne[cnt]=he[x],he[x]=cnt;}
  13. void dfs(int x)
  14. {
  15. in[x]=++I;for(int i=1;i<=15;i++) anc[x][i]=anc[anc[x][i-1]][i-1];
  16. for(int i=he[x],y;i;i=ne[i]) if((y=to[i])!=anc[x][0]) anc[y][0]=x,dep[y]=dep[x]+1,dfs(y);
  17. ou[x]=I;
  18. }
  19. int find(int x,int y){for(int i=15;~i;i--) if((1<<i)<=y) x=anc[x][i],y-=(1<<i);return x;}
  20. void upd(int x,int a){for(int i=x;i<=n;i+=i&-i) f[i]+=a;}
  21. int que(int x){int ans=0;for(int i=x;i;i-=i&-i) ans+=f[i];return ans;}
  22. void solve(int b,int e,int l,int r,int L,int R)//be:询问 lr:修改 LR:权值
  23. {
  24. if(b>e) return;
  25. if(L==R){for(int i=b;i<=e;i++) ans[q[i].z]=L;return;}//权值只有一种,直接记录区间内的答案
  26. int MID=(L+R)>>1,mid=l-1,p=l;//整体二分时,只用扫左一半的修改,然后如果数量不够就在以后的右边进行递归处理,够就在以后的左边进行递归处理
  27. for(int i=b;i<=e;i++) vl[q[i].z]=0;sort(a+l,a+r+1,cmp);
  28. while(mid<r&&a[mid+1].v<=MID) mid++;sort(a+l,a+mid+1);
  29. for(int i=b;i<=e;i++)
  30. {
  31. while(p<=mid&&a[p].x<=q[i].x) upd(a[p].y,a[p].w),upd(a[p].z+1,-a[p].w),p++;
  32. vl[q[i].z]+=que(q[i].y);//对每个点累加覆盖它的矩阵
  33. }
  34. while(p>l) p--,upd(a[p].y,-a[p].w),upd(a[p].z+1,a[p].w);//还原
  35. for(int i=(p=b);i<=e;i++) if(val[q[i].z]<=vl[q[i].z]) t[p++]=q[i];//够的
  36. for(int i=(p=e);i>=b;i--) if(val[q[i].z]>vl[q[i].z]) t[p--]=q[i];//不够的
  37. for(int i=b;i<=e;q[i]=t[i],i++) if(~vl[q[i].z]&&val[q[i].z]>vl[q[i].z]) val[q[i].z]-=vl[q[i].z],vl[q[i].z]=-1;//减去已经覆盖的
  38. solve(b,p,l,mid,L,MID),solve(p+1,e,mid+1,r,MID+1,R);
  39. }
  40. int main()
  41. {
  42. scanf("%d%d%d",&n,&m,&k);
  43. for(int i=2;i<=n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
  44. dfs(1);
  45. for(int i=1;i<=m;i++)
  46. {
  47. scanf("%d%d%d",&x,&y,&z);
  48. if(dep[x]>dep[y]) swap(x,y);
  49. if(dep[x]<dep[y]&&anc[g=find(y,dep[y]-dep[x]-1)][0]==x)//x是y的祖先,xy路径上x的直系儿子子树之外->y子树之内的路径都可以
  50. {
  51. a[++tot]=nod(1,in[y],ou[y],z,1);
  52. a[++tot]=nod(in[g],in[y],ou[y],z,-1);
  53. a[++tot]=nod(ou[g]+1,in[y],ou[y],z,1);//右端点是n,所以不用添加
  54. }
  55. else a[++tot]=nod(in[x],in[y],ou[y],z,1),a[++tot]=nod(ou[x]+1,in[y],ou[y],z,-1);//x和y没有祖先关系,x的子树内->y的子树内的路径都可以
  56. }
  57. for(int i=1;i<=k;i++) scanf("%d%d%d",&x,&y,&val[i]),q[i]=nod(in[x],in[y],i,0,0),q[i+k]=nod(in[y],in[x],i,0,0);
  58. sort(q+1,q+k*2+1),solve(1,k*2,1,tot,1,1000000000);
  59. for(int i=1;i<=k;i++)printf("%d\n",ans[i]);
  60. }

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

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

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

  2. 计蒜客A1998 Ka Chang (分块+dfs序+树状数组)

    题意 给你一个\(1e5\)的有点权的树,有\(1e5\)个操作: 1.给第\(x\)层的点加上\(y\) 2.求以\(x\)为根的子树的点权和 思路 首先处理出层数为x的所有点 操作2一般都是用df ...

  3. HDU 3887:Counting Offspring(DFS序+树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=3887 题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的. 思路:这题和那道苹果树是一样 ...

  4. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  5. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  6. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  7. 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  8. [BZOJ1103][POI2007]大都市meg dfs序+树状数组

    Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n ...

  9. 2018.10.20 NOIP模拟 巧克力(trie树+dfs序+树状数组)

    传送门 好题啊. 考虑前面的32分,直接维护后缀trietrietrie树就行了. 如果#号不在字符串首? 只需要维护第一个#前面的字符串和最后一个#后面的字符串. 分开用两棵trie树并且维护第一棵 ...

随机推荐

  1. nginx tcp负载均衡配置

    1. nginx从1.9.0后引入模块ngx_stream_core_module,模块是没有编译的,需要用到编译需添加--with-stream配置参数 2. 在 nginx.conf 文件中, 与 ...

  2. 股票F10

    [股票F10] 股票非行情类的基本面资料统称为股票F10   在各种金融行情终端软件中,用户通过键盘上的F10快捷键,可迅速查看上市公司的非行情信息,诸如:公司概况.财务数据.公司公告.公司新闻.经营 ...

  3. Go Methods and Interfaces

    [Go Methods and Interfaces] 1.Go does not have classes. However, you can define methods on struct ty ...

  4. Excel VBA入门(八)单元格边框

    本文基于以下文件 http://pan.baidu.com/s/1nvJtsu9 (部分)内容预览: 1. 边框样式 Sub cell_format() Dim sht As Worksheet Di ...

  5. Eclipse自动补全修改

    一.前言 之前敲代码用的是文本工具sublime,转到Eclipse之后发现补全功能特别不方便,所以想根据自己的情况进行调整,具体有两点: 输入某些语句的前几个字母就能自动提示相关的完整语句 用tab ...

  6. Golang之一个简单的聊天机器人

    翠花,上代码 package main import ( "bufio" "fmt" "os" "strings" ) ...

  7. 自学PHP的野方法

    1.基础知识 最早的基础知识仅限于那么一点点的html和css,比牛毛还牛毛的一点点.所以最开始是从immoc上看视频和跟着练习,花了有一个多月,看完一个路径从:零开始学习ThinkPHP框架,由于基 ...

  8. change qt version

    https://blog.csdn.net/xiaoheibaqi/article/details/50777203 右键工程->设置qt project setting -->修改ver ...

  9. Laravel中Trait的用法实例详解

    本文实例讲述了Laravel中Trait的用法.分享给大家供大家参考,具体如下: 看看PHP官方手册对Trait的定义: 自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 trait ...

  10. python pip 代理设置

    pip install --proxy="user:password@server:port" packagename origin url: http://xiuxixiuxi. ...