(バイナリワード感、アイデアまたはかなり速い出)
質問の意味:指定されたA
思考:各ノードのハンドルのお問い合わせは、この木のは非常に標準バイナリツリーであるので、その前処理を考え、木、そして確かにタイムアウトを通過する必要があるなら、私たちは、それぞれの子ノードから取得された各ツリーノードのために試すことができますその値とそれを保存(push_upが同じで木のラインのように動作)。そして、それぞれのお問い合わせについて
時間計算:前処理+クエリ:
宇宙複雑:前処理結果:
(最初のIで威力MLEを考え、その後、タイトルメモリで見つけ比較的大きい。長い時間がないライト・コード、実際にbreak文は、その上にあれば-else文をジャンプすることができると考え、長い時間(...)のための曲で書かれました。)
#include <cstdio>
#include <algorithm>
#include <vector>
#define LL long long
using 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 sort
int 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);
else
vec[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 sum
sum[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;
}