#447 Div2 D

题意

给一棵完全二叉树,每条边有权值为两点间的距离,每次询问 \(x, h\) ,从结点 \(x\) 出发到某一结点的最短路的距离 \(d\) 如果小于 \(h\) ,则答案加上 \(h - d\) ,考虑所有结点并输出答案。

分析

通过建树过程可以发现这是一棵完全二叉树,也就是说树很矮。

可以预处理这棵树,对于每一个结点,我们可以计算出以这个结点为根结点的子树中的所有结点到当前子树的根结点的距离,从根结点向下 DFS 即可,然后自下而上合并,类似归并排序合并的过程。再预处理下前缀和,这样就很容易求得子树中有多少结点到根结点的距离小于 \(h\) ,向上走 \(log(n)\) 次一定可以到根结点。

完全二叉树 很矮!祖先结点很少!很多情况都可以遍历(暴力)祖先结点!

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int f, s, mx;
int n, m, a[N], l[N], r[N];
vector<int> G[N];
vector<ll> S[N];
void mergeUp(int rt, int cl, int cr) {
int i = 0, j = 0;
while(i < cl || j < cr) {
if(i == cl) G[rt].push_back(r[j++]);
else if(j == cr) G[rt].push_back(l[i++]);
else {
if(l[i] < r[j]) G[rt].push_back(l[i++]);
else G[rt].push_back(r[j++]);
}
}
ll sum = 0;
for(int i = 0; i < G[rt].size(); i++) {
sum += G[rt][i];
S[rt].push_back(sum);
}
}
void build(int rt) {
if(rt >= s - mx + 1) return;
build(rt * 2);
build(rt * 2 + 1);
int cl = 0, cr = 0;
if(rt * 2 <= n) for(int i = 0; i < G[rt * 2].size(); i++) {
l[cl++] = G[rt * 2][i] + a[rt * 2];
}
if(rt * 2 + 1 <= n) for(int i = 0; i < G[rt * 2 + 1].size(); i++) {
r[cr++] = G[rt * 2 + 1][i] + a[rt * 2 + 1];
}
if(cl + cr > 0) mergeUp(rt, cl, cr);
}
int main() {
scanf("%d%d", &n, &m);
s = 1, mx = 1, f = 0;
while(s < n) {
mx *= 2;
s += mx;
f++;
}
for(int i = 1; i < n; i++) {
int x;
scanf("%d", &x);
a[i + 1] = x;
G[i].push_back(0);
}
G[n].push_back(0);
build(1);
while(m--) {
int now, h, pre = -1;
scanf("%d%d", &now, &h);
ll ans = h;
while(now) {
if(now != 1 && a[now] < h) ans += h - a[now];
if(pre == -1) {
int pos = lower_bound(G[now].begin(), G[now].end(), h) - G[now].begin() - 1;
if(pos > 0) ans += 1LL * pos * h - S[now][pos];
} else {
if(now * 2 == pre && now * 2 + 1 <= n) {
int nxt = now * 2 + 1;
int pos = lower_bound(G[nxt].begin(), G[nxt].end(), h - a[nxt]) - G[nxt].begin() - 1;
if(pos > 0) ans += 1LL * pos * (h - a[nxt]) - S[nxt][pos];
if(a[nxt] < h) ans += h - a[nxt];
} else if(now * 2 + 1 == pre && now * 2 <= n) {
int nxt = now * 2;
int pos = lower_bound(G[nxt].begin(), G[nxt].end(), h - a[nxt]) - G[nxt].begin() - 1;
if(pos > 0) ans += 1LL * pos * (h - a[nxt]) - S[nxt][pos];
if(a[nxt] < h) ans += h - a[nxt];
}
}
h -= a[now];
pre = now;
now /= 2;
}
cout << ans << endl;
}
return 0;
}

Codeforces #447 Div2 D的更多相关文章

  1. Codeforces #447 Div2 E

    #447 Div2 E 题意 给出一个由有向边构成的图,每条边上有蘑菇,假设有 \(n\) 个蘑菇,那么第一次走过这条边可以获得 \(n\) 个蘑菇,第二次 \(n-1\),第三次 \(n-1-2\) ...

  2. Codeforces #180 div2 C Parity Game

    // Codeforces #180 div2 C Parity Game // // 这个问题的意思被摄物体没有解释 // // 这个主题是如此的狠一点(对我来说,),不多说了这 // // 解决问 ...

  3. Codeforces #541 (Div2) - E. String Multiplication(动态规划)

    Problem   Codeforces #541 (Div2) - E. String Multiplication Time Limit: 2000 mSec Problem Descriptio ...

  4. Codeforces #541 (Div2) - F. Asya And Kittens(并查集+链表)

    Problem   Codeforces #541 (Div2) - F. Asya And Kittens Time Limit: 2000 mSec Problem Description Inp ...

  5. Codeforces #541 (Div2) - D. Gourmet choice(拓扑排序+并查集)

    Problem   Codeforces #541 (Div2) - D. Gourmet choice Time Limit: 2000 mSec Problem Description Input ...

  6. Codeforces #548 (Div2) - D.Steps to One(概率dp+数论)

    Problem   Codeforces #548 (Div2) - D.Steps to One Time Limit: 2000 mSec Problem Description Input Th ...

  7. 【Codeforces #312 div2 A】Lala Land and Apple Trees

    # [Codeforces #312 div2 A]Lala Land and Apple Trees 首先,此题的大意是在一条坐标轴上,有\(n\)个点,每个点的权值为\(a_{i}\),第一次从原 ...

  8. codeforces 447 A-E div2 补题

    A DZY Loves Hash 水题 #include<iostream> #include<cstdio> #include<cstdlib> #include ...

  9. Codeforces #263 div2 解题报告

    比赛链接:http://codeforces.com/contest/462 这次比赛的时候,刚刚注冊的时候非常想好好的做一下,可是网上喝了个小酒之后.也就迷迷糊糊地看了题目,做了几题.一觉醒来发现r ...

随机推荐

  1. 8086汇编语言 调用声卡播放wav文件(sound blaster)

    开更 大概最后做了一个能播放无损音乐(无压缩.不需解码)的播放器 原理是基于dosbox的模拟声卡,通过硬件之间的相互通讯做到的 关于详细内容接下来再讲. 一.从dosbox入手 我们知道cpu可以直 ...

  2. python数据绘图常用方法总结

    挖坑,以后还会更新吧 做数学建模画图使用了matplotlib和numpy,这里简单总结一下常用的用法 一.数据拟合 1.np.polyfit(x, y, n) 使用n次多项式去拟合x,y散点图,返回 ...

  3. 对C++ templates类模板的几点补充(Traits类模板特化)

    前一篇文章<浅谈C++ templates 函数模板.类模板以及非类型模板参数>简单的介绍了什么是函数模板(这个最简单),类模板以及非类型模板参数.本文对类模板再做几点补充. 文章目录1. ...

  4. 移动开发:美团外卖Android Lint代码检查实践

    概述 Lint是Google提供的Android静态代码检查工具,可以扫描并发现代码中潜在的问题,提醒开发人员及早修正,提高代码质量.除了Android原生提供的几百个Lint规则,还可以开发自定义L ...

  5. Android 异步通信:图文详解Handler机制工作原理

    前言 在Android开发的多线程应用场景中,Handler机制十分常用 今天,我将图文详解 Handler机制 的工作原理,希望你们会喜欢 目录 1. 定义 一套 Android 消息传递机制 2. ...

  6. [Leetcode] climbing stairs 爬楼梯

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  7. 用JavaScript写一个类似PHP print_r的函数

    PHP print_r的函数很好用,可以用来打印数组.对象等的结构与数据,可惜JavaScript并没有原生提供类似的函数.不过我们可以试着自己来实现这个函数,下面提供一些方法与思路. 方法一 fun ...

  8. linux 条件判断式

    1.利用if ...then if [ 判断条件 ];then 指令 fi 实例一 Y/N: #!/bin/bash #Program: # This program shows "Hell ...

  9. handler更新ui线程的基本用法

    1.因为费时操作要放子线程,更新UI要放UI线程(主线程),所以子线程和主线程通信,通信的话要用到handler这个东西. 这里讲的比较简单,举2个例子说明 2.使用post的是handler ,使用 ...

  10. HDU 1394 Minimum Inversion Number(树状数组/归并排序实现

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...