codeforces 894D

(Feeling of binary words, ideas or get out pretty fast)
meaning of the questions: given a n Node binary tree ( n<106 ), Each side having a weight value, then gives m m<105 ) An inquiry, seeking Ai Node Hi The tree nodes within a distance which can reach, through the request reaches the node and distance.

Thinking: If each node handles inquiries have to traverse the tree, then certainly a timeout, so think of pretreatment, because of this tree is very standard binary tree, then we can try for each tree node is obtained from each child node its value and save it (push_up operates like a tree line in the same). Then for each inquiry Ai We can use binary search to quickly find the node can reach it from the sub-tree node and below, and then want nothing more than to reach the rest of the node to go through Ai/2 or Ai1 The two nodes. Then we can get quickly Ai1 Fruit trees below. for Ai/2 The above point, we turn to traverse these stores until the roots, and then deal with each of these points corresponding Ai1 Subtree can be.

Time Complexity: Pretreatment + query: O ( n l o g( N ) + m l o g(n)2)
Space complexity: preprocessing results: O ( n l o g(n))

(At first I thought might MLE, and then found in the title memory is relatively large. Long time no write code, written in tune for a long time (actually thought that the break statement can jump on top of it if-else statements ...).)

#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;
}
Published 40 original articles · won praise 44 · views 90000 +

Guess you like

Origin blog.csdn.net/Site1997/article/details/78645249