(对二叉树有感觉的话,思路还是出得蛮快的)
题意:给定一个 n n节点二叉树(n<106n),每条边上有一个权值,然后给出 m m(m<105m)个询问,求 Ai A_i节点在 Hi H_i距离内能到达的树上哪些节点,求到达这些节点经过的距离之和。

思路:如果每次处理询问都要对树上节点遍历的话,肯定超时,于是想到预处理,由于这个树是很标准的二叉树,那么我们可以试试对于每个树节点,求出每个子节点距离它的值,并保存起来(就像线段树中的push_up操作一样)。然后对于每一个询问 Ai A_i,我们可以利用二分查找迅速求出这个节点所能到达它下面子树节点的距离和,然后想到达剩下的节点无非要经过 Ai/2 A_i/2或者 Ai⊕1 A_i\oplus1这两个节点。然后我们也可以迅速得到 Ai⊕1 A_i\oplus1下面子树的结果。对于 Ai/2 A_i/2上面的点,我们依次遍历这些店直到树根,然后每次处理这些点对应的 Ai⊕1 A_i\oplus1子树即可。

时间复杂度:预处理+查询: O(nlog(n)+mlog(n)2) O(nlog(n) + mlog(n)^2)
空间复杂度:预处理的结果: O(nlog(n)) O(nlog(n))

(开始以为可能会MLE,然后发现题目中内存比较大。好久没写代码,写的时候调了半天(居然以为break语句能跳出它上面的if-else语句…)。)

#include <cstdio>
#include <algorithm>
#include <vector>
#define LL long longusing namespace std;
const int maxn = 1000050;
const int inf = 0x3f3f3f3f;int len[maxn][2];
vector<int> vec[maxn];
vector<LL> sum[maxn];void push_up(int p, int n) {// merge sortint l = p<<1, r = p<<1|1, i = 0, j = 0;int l_len = len[p][0], r_len = r<=n? len[p][1]:0;while(i < (int)vec[l].size()-1 && j < (int)vec[r].size()-1) {if(vec[l][i]+l_len < vec[r][j]+r_len)vec[p].push_back(vec[l][i++]+l_len);elsevec[p].push_back(vec[r][j++]+r_len);if(vec[p].back() >= inf) break ;}while(i < (int)vec[l].size()-1 && vec[p].back() < inf)vec[p].push_back(vec[l][i++]+l_len);while(j < (int)vec[r].size()-1 && vec[p].back() < inf)vec[p].push_back(vec[r][j++]+r_len);if(vec[p].back() >= inf) vec[p].pop_back();// calculate prefix sumsum[p].push_back(vec[p][0]);for(int k=1; k<(int)vec[p].size(); k++) {sum[p].push_back(vec[p][k]);sum[p][k] += sum[p][k-1];}return ;
}void build(int p, int n) {int lson = p<<1, rson = p<<1|1;if(lson <= n) build(lson, n);if(rson <= n) build(rson, n);vec[p].clear();vec[p].push_back(0);if(lson <= n || rson <= n)push_up(p, n);vec[p].push_back(inf);return ;
}LL get_sum(int n, int id, int h) {LL ret = h;int pos = upper_bound(vec[id].begin(), vec[id].end(), h) - vec[id].begin() - 1;if(pos >= 1) ret += (LL)h*pos - sum[id][pos];//printf("ret1 : %I64d\n",ret);while(id != 1) {h -= len[id/2][id&1];if(h > 0) ret += h;else break ;//printf("ret2 : %I64d\n",ret);int id_2 = id ^ 1, branch = len[id/2][id_2&1];if(id_2 <= n && h-branch > 0) {ret += h-branch;int pos = upper_bound(vec[id_2].begin(), vec[id_2].end(), h-branch) - vec[id_2].begin() - 1;if(pos >= 1) ret += (LL)(h-branch)*pos - sum[id_2][pos];//printf("ret3 : %I64d\n",ret);}id /= 2;}return ret;
}int main() {int n, m;scanf("%d%d",&n,&m);for(int i=1; i<n; i++) {int t, st = (i+1)/2;scanf("%d",&t);len[st][(i+1)&1] = t;}build(1, n);while(m --) {int id, h;scanf("%d%d",&id,&h);LL ans = get_sum(n, id, h);printf("%I64d\n",ans);}return 0;
}

codeforces 894D相关推荐

  1. CodeForces 375D Tree and Queries

    传送门:https://codeforces.com/problemset/problem/375/D 题意: 给你一颗有根树,树上每个节点都有其对应的颜色,有m次询问,每次问你以点v为父节点的子树内 ...

  2. 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)

    题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...

  3. 【codeforces 812C】Sagheer and Nubian Market

    [题目链接]:http://codeforces.com/contest/812/problem/C [题意] 给你n个物品; 你可以选购k个物品;则 每个物品有一个基础价值; 然后还有一个附加价值; ...

  4. CodeForces 获得数据

    针对程序的输出可以看见 CodeForces :当输入.输出超过一定字符,会隐藏内容 所以:分若干个程序进行输入数据的获取 1. 1 for (i=1;i<=q;i++) 2 { 3 scanf ...

  5. codeforces水题100道 第二十七题 Codeforces Round #172 (Div. 2) A. Word Capitalization (strings)...

    题目链接:http://www.codeforces.com/problemset/problem/281/A 题意:将一个英文字母的首字母变成大写,然后输出. C++代码: #include < ...

  6. CodeForces 595A

    题目链接: http://codeforces.com/problemset/problem/595/A 题意: 一栋楼,有n层,每层有m户,每户有2个窗户,问这栋楼还有多少户没有睡觉(只要一个窗户灯 ...

  7. codeforces A. Jeff and Digits 解题报告

    题目链接:http://codeforces.com/problemset/problem/352/A 题目意思:给定一个只有0或5组成的序列,你要重新编排这个序列(当然你可以不取尽这些数字),使得这 ...

  8. Codeforces Round #506 (Div. 3)

    Codeforces Round #506 (Div. 3) 实习期间事不多,对div3 面向题解和数据编程了一波 A. Many Equal Substrings 题目链接 A题就是找后缀和前缀重合 ...

  9. Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈)

    Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈) 标签: codeforces 2017-06-02 11:41 29人阅读 ...

最新文章

  1. 公司新来了个大神,一次分享他的 9 大技能
  2. windows系统用什么web服务器好_墙体保温系统用什么材料比较好
  3. c语言中通过分隔符取字符串,C语言切割多层字符串(strtok_r strtok使用方法)
  4. 常用的后端命令 【笔记】
  5. 2021-08-08 idea 连接Mysql
  6. 4个步骤教你建立中后台后台通用权限管理系统
  7. 计算机类期刊投稿心得
  8. laragon mysql版本_laragon mysql8 安装
  9. IAM统一身份认证服务
  10. vant 底部导航栏 中间凸起
  11. 《idea》idea快捷键总结,IntelliJ IDEA快捷键.
  12. hive中开窗函数 :percent_rank()的含义
  13. 在WINDOWS 下删除EISA配置的隐藏分区
  14. 微信小程序 消息订阅 长期订阅 一次授权 多次接收 微信服务通知
  15. 接触角测量的常用测量法
  16. Win10 局域网共享文件遇到的疑难杂症通用解决策略
  17. 基于SpringBoot+Vue 实现的OA自动化办公系统
  18. csv的文件用excel打开方式 一键解决证件号/订单号后四位变0的情况
  19. 三八节与芊芊一起赏雪
  20. 清华同方服务器做系统,清华同方云服务器底层操作软件

热门文章

  1. ubuntu20双系统+Mininet+Floodlight+eclipse luna
  2. 2022年全球高净值人士净流入前十国家阿联酋居首;京沪跻身全球百万富翁最多城市前十;美中印亿万富翁数量全球前三 | 美通社头条...
  3. (C语言版)猴子吃桃问题
  4. 在office2007中用vba代码写出二维码生成代码
  5. em模型补缺失值_如何填补缺失值?看SPSS提供的简单方法
  6. 推荐10个Java方向最热门的开源项目(8月)
  7. 8.6 正睿暑期集训营 Day3
  8. Android系统基础架构
  9. 用户调查:给粉丝群发消息,红包,打赏的一些想法
  10. php curl init 用法,curl_init_php curl_init函数用法