Codeforces #447 Div2 D
#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的更多相关文章
- Codeforces #447 Div2 E
#447 Div2 E 题意 给出一个由有向边构成的图,每条边上有蘑菇,假设有 \(n\) 个蘑菇,那么第一次走过这条边可以获得 \(n\) 个蘑菇,第二次 \(n-1\),第三次 \(n-1-2\) ...
- Codeforces #180 div2 C Parity Game
// Codeforces #180 div2 C Parity Game // // 这个问题的意思被摄物体没有解释 // // 这个主题是如此的狠一点(对我来说,),不多说了这 // // 解决问 ...
- Codeforces #541 (Div2) - E. String Multiplication(动态规划)
Problem Codeforces #541 (Div2) - E. String Multiplication Time Limit: 2000 mSec Problem Descriptio ...
- Codeforces #541 (Div2) - F. Asya And Kittens(并查集+链表)
Problem Codeforces #541 (Div2) - F. Asya And Kittens Time Limit: 2000 mSec Problem Description Inp ...
- Codeforces #541 (Div2) - D. Gourmet choice(拓扑排序+并查集)
Problem Codeforces #541 (Div2) - D. Gourmet choice Time Limit: 2000 mSec Problem Description Input ...
- Codeforces #548 (Div2) - D.Steps to One(概率dp+数论)
Problem Codeforces #548 (Div2) - D.Steps to One Time Limit: 2000 mSec Problem Description Input Th ...
- 【Codeforces #312 div2 A】Lala Land and Apple Trees
# [Codeforces #312 div2 A]Lala Land and Apple Trees 首先,此题的大意是在一条坐标轴上,有\(n\)个点,每个点的权值为\(a_{i}\),第一次从原 ...
- codeforces 447 A-E div2 补题
A DZY Loves Hash 水题 #include<iostream> #include<cstdio> #include<cstdlib> #include ...
- Codeforces #263 div2 解题报告
比赛链接:http://codeforces.com/contest/462 这次比赛的时候,刚刚注冊的时候非常想好好的做一下,可是网上喝了个小酒之后.也就迷迷糊糊地看了题目,做了几题.一觉醒来发现r ...
随机推荐
- 【转】Win7装不上Office2010 提示MSXML 6.10.1129.0
转自:http://zhidao.baidu.com/link?url=aZPbpBu0Fb7rc8HCb_NuonuZ4ET_BB8_NgZ96tCpB9dyuUyWVwMl78MLa7rh-rfx ...
- 【考试记录】4.8 Path (网络流 —— 劲题)
手抄代码 + 学习指针 + 冥思苦想一晚上终于——在一瞬间开窍了.果然题目都是这样:突破了一个点,一切都是柳暗花明. 题面描述: 样例: 这道题目,首先注意到给定的边的性质:这些边在平面上构成了一棵树 ...
- [洛谷P2824][HEOI2016/TJOI2016]排序
题目大意:一个全排列,两种操作: 1. $0\;l\;r:$把$[l,r]$升序排序2. $1\;l\;r:$把$[l,r]$降序排序 最后询问第$k$位是什么 题解:二分答案,把比这个数大的赋成$1 ...
- [洛谷P1278]单词游戏
题目大意:给一个有$n(n\leqslant16)$个单词的字典,求单词接龙的最大长度 题解:发现$n$很小,可以状压,令$f_{i,j}$表示选的数的状态为$i$,最后一个字母是$j$的最大长度. ...
- [Leetcode] set matrix zeroes 矩阵置零
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. click ...
- 洛谷P4588 [TJOI2018]数学计算 【线段树】
题目链接 洛谷P4588 题解 用线段树维护即可 #include<algorithm> #include<iostream> #include<cstring> ...
- ionic2 手风琴效果
user.ts import { Component } from '@angular/core';import { IonicPage, NavController, NavParams } fro ...
- fuser命令找到占用资源的进程
fuser 概述 fuser命令是用来显示所有正在使用着指定的file, file system 或者 sockets的进程信息. 例一: #fuser –m –u /mnt/usb1 /mnt/us ...
- xmlns:sys="clr-namespace:System;assembly=mscorlib" NOTE: System;与assembly中间不能有空格
xmlns:sys="clr-namespace:System;assembly=mscorlib" NOTE: System;与assembly中间不能有空格 否则报错, Er ...
- 数学:Lucas定理
利用Lucas定理解决大组合数取模 Lucas定理是用来求 C(n,m) mod p,p为素数的值.(注意:p一定是素数) Lucas定理用来解决大组合数求模是很有用的 Lucas定理最大的数据处理能 ...