【题目】E. NN country

【题意】给定n个点的树和m条链,q次询问一条链(a,b)最少被多少条给定的链覆盖。\(n,m,q \leq 2*10^5\)。

【算法】树上倍增+二维数点(树状数组)

先从半链角度考虑。将每条给定链和每个询问拆成向上的一段和向下的一段。那么假设询问的半链最低端节点为x,贪心地选择x子树内向上延伸最远的给定半链(假设最高点为y),再从y继续贪心直至超过半链最顶端节点。再只考虑半链的前提下贪心显然正确。

但是我们注意到,这样贪心的复杂度是不正确的,因为如果每次只跳一条边的话复杂度就是链长了。树上跳点容易想到倍增,令\(f_{i,j}\)表示点\(i\)贪心跳\(2^j\)条链能到达的最高点,这样就可以直接倍增到最顶端节点了。注意不存在的点设为0。初始化\(f_{x,0}\)的过程可以用dfs实现,每个点比较自身出发的链的最高点和儿子子树出发的链的最高点。

接下来考虑全链。分别从两个端点倍增到最高的在lca之下的点处(需要特判一个点为另一个点的lca的情况),假设为x和y,那么接下来的问题就是判断x和y是否属于同一条链,如果是那么答案+1,否则答案+2。这实际上在询问是否有一条链的一个端点在x子树内,另一个端点在y子树内。进一步抽象成dfs序后,就是矩阵数点问题了,可以用扫描线(离线)+树状数组解决。注意数点要求有序点对,所以将所有链强制左端点的dfs序小。

复杂度\(O(n \ \ log \ \ n)\)。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define lowbit(x) (x&-x)
  5. bool isdigit(char c){return c>='0'&&c<='9';}
  6. int read(){
  7. int s=0,t=1;char c;
  8. while(!isdigit(c=getchar()))if(c=='-')t=-1;
  9. do{s=s*10+c-'0';}while(isdigit(c=getchar()));
  10. return s*t;
  11. }
  12. using namespace std;
  13. const int maxn=200010;
  14. int n,deep[maxn],first[maxn],tot,f[maxn][22],fac[22],ans[maxn],in[maxn],ou[maxn],cnt,ask,c[maxn],ANS[maxn];
  15. struct edge{int v,from;}e[maxn*2];
  16. struct cyc{
  17. int x,y,k,id;
  18. bool operator < (const cyc &a)const{
  19. return x<a.x||(x==a.x&&id<a.id);
  20. }
  21. }d[maxn*5];
  22. void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
  23. void modify(int x,int k){for(int i=x;i<=n;i+=lowbit(i))c[i]+=k;}
  24. int query(int x){if(!x)return 0;int ans=0;for(int i=x;i>=1;i-=lowbit(i))ans+=c[i];return ans;}
  25. namespace lca{
  26. int f[maxn][22];
  27. void dfs(int x,int fa){
  28. in[x]=++cnt;
  29. for(int j=1;(1<<j)<=deep[x];j++)f[x][j]=f[f[x][j-1]][j-1];
  30. for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
  31. deep[e[i].v]=deep[x]+1;
  32. f[e[i].v][0]=x;
  33. dfs(e[i].v,x);
  34. }
  35. ou[x]=cnt;
  36. }
  37. int lca(int x,int y){
  38. if(deep[x]<deep[y])swap(x,y);
  39. int d=deep[x]-deep[y];
  40. for(int j=0;(1<<j)<=d;j++)if((1<<j)&d)x=f[x][j];
  41. if(x==y)return x;
  42. for(int j=20;j>=0;j--)if((1<<j)<=deep[x]&&f[x][j]!=f[y][j]){
  43. x=f[x][j],y=f[y][j];
  44. }
  45. return f[x][0];
  46. }
  47. }
  48. void dfs(int x,int fa){
  49. for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
  50. dfs(e[i].v,x);
  51. if(!f[x][0]||(f[e[i].v][0]&&deep[f[e[i].v][0]]<deep[f[x][0]]))f[x][0]=f[e[i].v][0];//!0
  52. }
  53. }
  54. int main(){
  55. n=read();
  56. for(int i=2;i<=n;i++){
  57. int u=read();
  58. insert(u,i);insert(i,u);
  59. }
  60. lca::dfs(1,0);
  61. int m=read();
  62. for(int i=1;i<=m;i++){
  63. int a=read(),b=read(),t=lca::lca(a,b);
  64. if(in[a]>in[b])swap(a,b);//swap
  65. if(!f[a][0]||deep[t]<deep[f[a][0]])f[a][0]=t;
  66. if(!f[b][0]||deep[t]<deep[f[b][0]])f[b][0]=t;
  67. d[++ask]=(cyc){in[a],in[b],1,0};
  68. }
  69. dfs(1,0);
  70. for(int x=1;x<=n;x++)if(f[x][0]==x)f[x][0]=0;//can't set itself
  71. for(int j=1;j<=20;j++)for(int x=1;x<=n;x++)f[x][j]=f[f[x][j-1]][j-1];
  72. int q=read();
  73. fac[0]=1;for(int i=1;i<=20;i++)fac[i]=fac[i-1]*2;
  74. for(int i=1;i<=q;i++){
  75. int x=read(),y=read(),t=lca::lca(x,y);
  76. if(in[x]>in[y])swap(x,y);//
  77. for(int j=20;j>=0;j--)if(f[x][j]&&deep[f[x][j]]>deep[t])x=f[x][j],ans[i]+=fac[j];
  78. for(int j=20;j>=0;j--)if(f[y][j]&&deep[f[y][j]]>deep[t])y=f[y][j],ans[i]+=fac[j];
  79. if((!f[x][0]&&x!=t)||(!f[y][0]&&y!=t)){ans[i]=-1;continue;}
  80. if(x==t||y==t)ans[i]++;else{
  81. ans[i]+=2;
  82. d[++ask]=(cyc){ou[x],ou[y],1,i};
  83. d[++ask]=(cyc){in[x]-1,ou[y],-1,i};
  84. d[++ask]=(cyc){ou[x],in[y]-1,-1,i};
  85. d[++ask]=(cyc){in[x]-1,in[y]-1,1,i};
  86. }
  87. }
  88. sort(d+1,d+ask+1);
  89. for(int i=1;i<=ask;i++){
  90. if(!d[i].id){
  91. modify(d[i].y,d[i].k);
  92. }
  93. else{
  94. ANS[d[i].id]+=d[i].k*query(d[i].y);
  95. }
  96. }
  97. for(int i=1;i<=q;i++)printf("%d\n",ans[i]-(ANS[i]>0));
  98. return 0;
  99. }

【CodeForces】983 E. NN country 树上倍增+二维数点的更多相关文章

  1. Codeforces 848C Goodbye Souvenir [CDQ分治,二维数点]

    洛谷 Codeforces 这题我写了四种做法-- 思路 不管做法怎样,思路都是一样的. 好吧,其实不一样,有细微的差别. 第一种 考虑位置\(x\)对区间\([l,r]\)有\(\pm x\)的贡献 ...

  2. loj#6041. 「雅礼集训 2017 Day7」事情的相似度(SAM set启发式合并 二维数点)

    题意 题目链接 Sol 只会后缀数组+暴躁莫队套set\(n \sqrt{n} \log n\)但绝对跑不过去. 正解是SAM + set启发式合并 + 二维数点/ SAM + LCT 但是我只会第一 ...

  3. loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分

    $ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinob ...

  4. 【线段树 扫描线 二维数点】loj#6276. 果树

    路径计数转成二维数点很妙啊 题目描述 NiroBC 姐姐是个活泼的少女,她十分喜欢爬树,而她家门口正好有一棵果树,正好满足了她爬树的需求. 这颗果树有 $N$ 个节点,标号 $1 \ldots N$ ...

  5. 6.6 省选模拟赛 线段 二维数点问题 树套树 CDQ分治

    LINK:线段 还是太菜了 没看出这道题真正的模型 我真是一个典型的没脑子选手. 考虑如何查询答案. 每次在一个线段x的状态被更改后 可以发现有影响的是 和x相连那段极长连续1子段. 设这个子段左端点 ...

  6. BZOJ4822[Cqoi2017]老C的任务——树状数组(二维数点)

    题目描述 老 C 是个程序员.     最近老 C 从老板那里接到了一个任务——给城市中的手机基站写个管理系统.作为经验丰富的程序员,老 C 轻松 地完成了系统的大部分功能,并把其中一个功能交给你来实 ...

  7. BZOJ1935: [Shoi2007]Tree 园丁的烦恼(树状数组 二维数点)

    题意 题目链接 Sol 二维数点板子题 首先把询问拆成四个矩形 然后离散化+树状数组统计就可以了 // luogu-judger-enable-o2 #include<bits/stdc++.h ...

  8. 初涉二维数点问题&&bzoj1935: [Shoi2007]Tree 园丁的烦恼

    离线好评 Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个 ...

  9. [jzoj 5926] [NOIP2018模拟10.25] naive 的图 解题报告(kruskal重构树+二维数点)

    题目链接: https://jzoj.net/senior/#main/show/5926 题目: 题解: 显然最小的最大路径在最小生成树上(最小生成树=最小瓶颈生成树) 于是我们建出kruskal重 ...

随机推荐

  1. CocoaPods 遇到 A host target is a "parent" target which embeds a "child" target 问题解决

    正在开发的项目中,集成RN,在使用cocoapods 时候,pod install 遇到如下问题: [!] Unable to find host target(s) for ****Extensio ...

  2. 20181023-3 每周例行报告(添加PSP)

    此作业要求:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2100] 一.本周PSP表格 类型 任务 开始时间 结束时间 中断时间 净时 ...

  3. 12.16daily_scrum

    这个阶段,我们组需要攻克的技术难题一个是测试及美化界面,另一个是在M1阶段的基础上进一步细化和完善悬浮窗的功能,具体的工作内容如下: 具体工作: 小组成员 今日任务 明日任务 工作时间 李睿琦 图片笔 ...

  4. M1事后分析报告--We have power to change the origin state

    M1事后分析报告 设计与实现 我们发的软件解决的问题?是否满足后面小组的要求?是否能够完全拟合前期目标? 答: 前期我们的软件完成量并不是特别让人满意,我们组在完成这些任务量之后,发现有很多地方是在做 ...

  5. 实训一(cocos2d-x相关)

    实训内容简介: 大四开始前系里安排的的集中实践环节,根据要求,开发app应用软件. 目标app:Stick_mxj 目的:继续对cocos2d-x的学习,完成实践环节,解决现在对引擎不是很清楚的一些问 ...

  6. linq to sql中的自动缓存(对象跟踪)

    linq to sql中,对于同一个DataContext上下文环境,根据表主键选择记录时(当然这里所指的“记录”会自动转成“对象”),如果该记录已经被select过,默认情况下会被自动缓存下来,下次 ...

  7. Leetcode——37.解数独 [##]

    @author: ZZQ @software: PyCharm @file: leetcode37_solveSudoku.py @time: 2018/11/20 16:41 思路:递归回溯 首先, ...

  8. ElasticSearch 2 (2) - Setup

    ElasticSearch 2.1.1 (2) - Setup Installation Elasticsearch can be started using: $ bin/elasticsearc ...

  9. 个人作业-Week 2 代码复审

    一.概要部分 1.代码能符合需求和规格说明么? 经过我自己的测试和助教的检测,他的代码符合需求和规格的说明. 2.代码设计是否有周全的考虑? 这里代码设计我们是从两个方面检查的: 对方处理控制台输入的 ...

  10. MYSQL 解决中文字符集乱码问题的方法

    修改 /etc/mysql/my.cnf 增加内容 [client] default-character-set = utf8mb4 [mysql] default-character-set = u ...