题面叙述

题目给出两种操作:
操作1是将一个权重为W的点加到树的某个节点下。
操作2是询问一个从R开始的序列的最长可能长度。
其中这个序列要这样找:从R开始,沿着祖先方向往上找,凡是权重大于等于当前序列最后一个点的要被选上,然后更新序列。权重和要最大且小于X。

题解

我们设定一个数组nxt[i]表示i的祖先中,第一个权重大于等于i的权重的节点。再定义一个数组sum[i]表示从i出发,一直往上走所形成的满足题意序列的权重和,我们可以认为sum[i]是一个前缀和。
下面我们的关键是怎么来维护nxt数组和sum数组,如果新来一个R节点,把它放在U节点下面的话,怎么找到这条链上第一个权重大于等于R的权重的节点成了问题。
我们最直接想到的方法是暴力,一个一个往上枚举,但是这样复杂的显然会爆炸。所以我们用倍增的思想。即nxt[i][j]表示从i节点出发的满足题意的序列中距离i为2j2j2^j的点的编号。
那么我们可以用二分搜索的方式快速的找到这条链上第一个权重大于等于R的权重的节点。时间复杂度O((logn)2)O((logn)2)O({(logn)}^2)。
然后就得到了nxt[R][0],nxt[R][i]=upstep(nxt[R][0],2i−1)nxt[R][i]=upstep(nxt[R][0],2i−1)nxt[R][i] = upstep(nxt[R][0] ,2^i-1)
其中upstep(u,s)表示由u开始,往上走s步到达的节点。
回答询问也很简单,同样适用二分答案的方式,二分序列的长度,
找到满足sum[R]−sum[upstep(R,s)]<=Xsum[R]−sum[upstep(R,s)]<=Xsum[R]-sum[upstep(R,s)] 最大的s,s就是答案。时间复杂度同样是O((logn)2)O((logn)2)O({(logn)}^2)。


代码

#include <cstdio>
#include <iostream>
typedef long long ll;
const int maxn = 400007;
const ll inf = 1e18;
ll ws[maxn],sum[maxn],nxt[maxn][25],dep[maxn],p,q,Q,tp,last,cnt = 1;
int upstep(int rt,int step){int i = 0;int ans = rt;while(step){if(step&1) ans = nxt[ans][i];step >>= 1;i++;}return ans;
}
void op1(){ll R = last ^ p,W = last ^ q,U = ++cnt;ws[U] = W;if(ws[R] >= ws[U]) nxt[U][0] = R;else{ll l = 1,r = (cnt+1),mid,tar;while(r-l>1){mid = (l+r)/2;tar = upstep(R,mid);if(ws[tar] >= ws[U]) r = mid;else l = mid;}tar = upstep(R,l);if(ws[tar] >= ws[U]) nxt[U][0] = tar;else nxt[U][0] = nxt[tar][0];}sum[U] = sum[nxt[U][0]] + W;dep[U] = dep[nxt[U][0]] + 1;for(int i = 1;i < 21;++i) nxt[U][i] = upstep(nxt[U][0],(1<<i)-1);//printf("%lld\n",nxt[U][0]);
}
void op2(){ll R = last ^ p,X = last ^ q;if(X < ws[R]){printf("%lld\n",last = 0);return ;}ll l = 1,r = dep[R]+1,mid,tar,sm;while(r-l>1){mid = (l+r)/2;tar = upstep(R,mid);sm = sum[R] - sum[tar];//printf("sm = %lld,tar = %lld,mid = %lld\n",sm,tar,mid);if(sm > X) r = mid;else l = mid;//printf("l = %lld,r = %lld\n",l,r);}tar = upstep(R,l);printf("%lld\n",last = l);
}
int main(){dep[1] = 1;ws[0] = inf;scanf("%lld",&Q);while(Q--){scanf("%lld%lld%lld",&tp,&p,&q);if(tp == 1) op1();else op2();}
}

codeforces 932D Tree 倍增法+二分搜索相关推荐

  1. Codeforces 932D - Tree

    932D - Tree 思路: 树上倍增 anc[i][u]:u的2^i祖先 mx[i][u]:u到它的2^i祖先之间的最大值,不包括u pre[i][u]:以u开始的递增序列的2^i祖先 sum[i ...

  2. CodeForces - 932D Tree(树上倍增,好题)

    题目链接:点击查看 题目大意:给出一棵树,初始时只有一个节点1,权值为0,后续有 n 个操作,每次操作分为两种情况: 1 u val:向树中插入一个新的节点,其父节点为 u ,权值为 val 2 u ...

  3. 主席树 + 树上倍增 ---- codeforces 587C[树上倍增或者主席树]

    题目链接 给定一棵n个点的树,给定m个人(m≤n)在哪个点上的信息,每个点可以有任意个人:然后给q个询问,每次问u到v上的路径有的点上编号最小的k(k≤10)个人(没有那么多人就该有多少人输出多少人) ...

  4. 01分数规划c语言,POJ 1330(LCA/倍增法模板)

    链接:http://poj.org/problem?id=1330 题意:q次询问求两个点u,v的LCA 思路:LCA模板题,首先找一下树的根,然后dfs预处理求LCA(u,v) AC代码: #inc ...

  5. poj 1470(简单LCA 倍增法)

    题意:给你一个树,有若干个询问,然后让你统计每个结点在询问中做了几次LCA.按照结点顺序输出. 思路:这也是简单的LCA题目,我用的是倍增法.每次查询在相应结点标记上++,最后输出即可.这道题的输入处 ...

  6. (转)LCA模板(倍增法)

    插眼:点击查看 用法:求树上两个节点的公共祖先 代码: const int N=1e5+100;int n;//节点个数int k=log2(n)+1;int dp[N][20];//倍增法int d ...

  7. 图论--LCA--树上倍增法(在线)

    /** LCA在线算法(倍增法) */ const int MAXN = 10010; const int DEG = 20;struct Edge {int to, next; } edge[MAX ...

  8. [POJ 1330] Nearest Common Ancestors (倍增法)

    题目同上篇,最近公共祖先. 因为没有清零tot,RE了好多次TAT 一定要初始化啊!! 1 #include<cstdio> 2 #include<cstring> 3 #in ...

  9. poj1470 LCA倍增法

    倍增法模板题 #include<iostream> #include<cstring> #include<cstdio> #include<queue> ...

最新文章

  1. 你可能不需要一个 JavaScript 框架(二)
  2. rsync+inotify的实现
  3. nagios(系统监控)
  4. vim多窗口使用技巧
  5. php程序里如何实现图片翻页,php图片上传代码一例-php 生成翻页链接(页码)列表的...-带多种分页方式的php分页类_169IT.COM...
  6. JDK和Spring中的设计模式
  7. mysql msql_MySQL数据库学习二 MSQL安装和配置
  8. VUE 全局监听sessionStorage变化
  9. 因服务器配置不当,热门直播平台 Twitch 的125GB 数据和源代码被泄露
  10. 统计某个路径下的总文件个数,及总行数(不含空行)
  11. 程序设计c语言文件,文件C语言程序设计.pdf
  12. win10亮度_安利一款PC端调节多显示器亮度的软件
  13. LeetCode Problems 903
  14. Win11键盘锁住怎么恢复?
  15. 2021考研复试面试形式:线上视频面试注意事项?
  16. NGUI-动画Tween
  17. 【猿说VUE】Visual Studio Code安装配置
  18. numpy——arry矩阵交换行或者交换列
  19. 数据库SQL语句检索相关
  20. 5.1声道转化为左右声道

热门文章

  1. ndr4108贴片晶振是多少频率_关于山羊挺身你知道多少?这些干货速来了解一下...
  2. 一张网页带你了解中秋节的前世今生
  3. [JS-DOM]DOM概述
  4. [PAT乙级]1018 锤子剪刀布
  5. LeetCode 965单值二叉树-简单
  6. TCP(发消息:简易代码实现)
  7. SpringCloud + Docker
  8. word List16
  9. HashMap实现LRU(最近最少使用)缓存更新算法
  10. kettle同步数据中文乱码问题解决