Codeforces Round #447(Div.2)Problem D Ralph And His Tour in Binary Country(归并排序+二分)

D. Ralph And His Tour in Binary Country
time limit per test
2.5 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Ralph is in the Binary Country. The Binary Country consists of n cities and (n - 1) bidirectional roads connecting the cities. The roads are numbered from 1 to (n - 1), the i-th road connects the city labeled  (here ⌊ x denotes the x rounded down to the nearest integer) and the city labeled (i + 1), and the length of the i-th road is Li.

Now Ralph gives you m queries. In each query he tells you some city Ai and an integer Hi. He wants to make some tours starting from this city. He can choose any city in the Binary Country (including Ai) as the terminal city for a tour. He gains happiness (Hi - L) during a tour, where L is the distance between the city Ai and the terminal city.

Ralph is interested in tours from Ai in which he can gain positive happiness. For each query, compute the sum of happiness gains for all such tours.

Ralph will never take the same tour twice or more (in one query), he will never pass the same city twice or more in one tour.

Input

The first line contains two integers n and m (1 ≤ n ≤ 1061 ≤ m ≤ 105).

(n - 1) lines follow, each line contains one integer Li (1 ≤ Li ≤ 105), which denotes the length of the i-th road.

m lines follow, each line contains two integers Ai and Hi (1 ≤ Ai ≤ n0 ≤ Hi ≤ 107).

Output

Print m lines, on the i-th line print one integer — the answer for the i-th query.

Examples
input
2 2
5
1 8
2 4
output
11
4
input
6 4
2
1
1
3
2
2 4
1 3
3 2
1 7
output
11
6
3
28
Note

Here is the explanation for the second sample.

Ralph's first query is to start tours from city 2 and Hi equals to 4. Here are the options:

  • He can choose city 5 as his terminal city. Since the distance between city 5 and city 2 is 3, he can gain happiness 4 - 3 = 1.
  • He can choose city 4 as his terminal city and gain happiness 3.
  • He can choose city 1 as his terminal city and gain happiness 2.
  • He can choose city 3 as his terminal city and gain happiness 1.
  • Note that Ralph can choose city 2 as his terminal city and gain happiness 4.
  • Ralph won't choose city 6 as his terminal city because the distance between city 6 and city 2 is 5, which leads to negative happiness for Ralph.

So the answer for the first query is 1 + 3 + 2 + 1 + 4 = 11.


【思路】

题目给了一颗有边权的完全二叉树,并在每一组询问给定起始点A和幸福值H,设从A出发到树上任何目标点(可能是自己)的距离为L,如果H - L为正值,则求它们的和。首先对这棵二叉树的每一个节点进行归并操作,得到其子树中的点到它的距离的升序排列,时间复杂度为O(NlogN),那么树上任意两点的距离就可求了。在树上,我们从给定的起点开始,幸福值remain为初始值,对它的距离数组进行二分搜索,找到小于remain的最大的那个元素的位置,加上remain乘以前半段这些元素的个数再减去它们的距离之和,上移节点迭代就是答案。


【代码】

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int MAXN = 1e6 + 5;

int n, m;
int len[MAXN], a[MAXN];
vector<int> ln[MAXN];
vector<long long> sum[MAXN];

void merge(int x, int y)
{
    int i = 0, j = 0, k = 0;
    while (i < ln[x].size() && j < ln[y].size()) {
        if (ln[x][i] <= ln[y][j] + len[y])
            a[k++] = ln[x][i++];
        else
            a[k++] = ln[y][j++] + len[y];
    }
    while (i < ln[x].size()) a[k++] = ln[x][i++];
    while (j < ln[y].size()) a[k++] = ln[y][j++] + len[y];
    ln[x].clear();
    for (int t = 0; t < k; t++) ln[x].push_back(a[t]);
}

long long binsearch(int pos, int remain)
{
    if (remain <= 0) return 0;
    int left = 0, right = ln[pos].size() - 1;
    while (left + 1 < right) {
        int mid = (left + right) >> 1;
        if (ln[pos][mid] <= remain)
            left = mid;
        else
            right = mid - 1;
    }
    int cnt;
    if (ln[pos][right] <= remain)
        cnt = right + 1;
    else
        cnt = left + 1;
    return (long long)remain * cnt - sum[pos][cnt - 1];
}

long long solve(int pos, int remain)
{
    long long ans = 0;
    int last= 0;
    while (pos >= 1 && remain > 0) {
        int lson = pos << 1, rson = pos << 1 | 1;
        ans += remain;
        if (lson <= n && lson != last) ans += binsearch(lson, remain - len[lson]);
        if (rson <= n && rson != last) ans += binsearch(rson, remain - len[rson]);
        remain -= len[pos];
        last = pos;
        pos >>= 1;
    }
    return ans;
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 2; i <= n; i++) scanf("%d", &len[i]);
    for (int i = 1; i <= n; i++) ln[i].push_back(0);
    for (int i = n; i >= 2; i--) merge(i >> 1, i);
    for (int i = 1; i <= n; i++) {
        sum[i].push_back(0);
        for (int j = 1; j < ln[i].size(); j++)
            sum[i].push_back(sum[i][j - 1] + (long long)ln[i][j]);
    }
    int origin, happiness;
    while (m--) {
        scanf("%d %d", &origin, &happiness);
        long long ans = solve(origin, happiness);
        printf("%lld\n", ans);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/shili_xu/article/details/78745451