XKC's basketball team【线段树查询】

XKC , the captain of the basketball team , is directing a train of nn team members. He makes all members stand in a row , and numbers them 1 cdots n1n from left to right.

The ability of the ii-th person is w_iwi , and if there is a guy whose ability is not less than w_i+mwi+m stands on his right , he will become angry. It means that the jj-th person will make the ii-th person angry if j>ij>i and w_j ge w_i+mwjwi+m.

We define the anger of the ii-th person as the number of people between him and the person , who makes him angry and the distance from him is the longest in those people. If there is no one who makes him angry , his anger is -11 .

Please calculate the anger of every team member .

Input

The first line contains two integers nn and m(2leq nleq 5*10^5, 0leq m leq 10^9)m(2n5105,0m109) .

The following  line contain nn integers w_1..w_n(0leq w_i leq 10^9)w1..wn(0wi109) .

Output

A row of nn integers separated by spaces , representing the anger of every member .

样例输入

6 1
3 4 5 6 2 10

样例输出

4 3 2 1 0 -1

题目大意:
1.给出一个长度为n的数列,给出m的值。问在数列中从右到左第一个比 arr[i] + m 大的值所在位置与 arr[i] 的所在位置之间夹着多少个数。
解题思路:
1.用线段树来记录区间最大值,优先从右子树开始查询是否存在大于 arr[i] + m的值,返回下标即该值在原数列中的位置,即可求得答案。
2.重要的是查询的值必须是在 i 的右边,否则输出 -1
代码如下:
 1 #include<stdio.h>
 2 #include<algorithm>
 3 using namespace std;
 4 const int MAXN = 5e5 + 10;
 5 
 6 int n, m;
 7 int a[MAXN], ANS[MAXN];
 8 
 9 struct Tree
10 {
11     int val, l, r;
12 }tree[4 * MAXN];
13 
14 void build(int k, int l, int r)
15 {
16     tree[k].l = l, tree[k].r = r;
17     if(l == r)
18     {
19         tree[k].val = a[l];
20         return ;
21     }
22     int mid = (l + r) / 2;
23     build(2 * k, l, mid);
24     build(2 * k + 1, mid + 1, r);
25     tree[k].val = max(tree[2 * k].val, tree[2 * k + 1].val);
26 }
27 
28 int query(int k, int goal)
29 {
30     if(tree[k].l == tree[k].r)
31         return tree[k].l;
32     if(tree[2 * k + 1].val >= goal)
33         return query(2 * k + 1, goal);
34     else if(tree[2 * k].val >= goal)
35         return query(2 * k, goal);
36     else
37         return -1;
38 }
39 
40 int main()
41 {
42     scanf("%d%d", &n, &m);
43     for(int i = 1; i <= n; i ++)
44         scanf("%d", &a[i]);
45     build(1, 1, n); //线段树建树
46     for(int i = 1; i <= n; i ++)
47     {
48         int flag = 0;
49         int ans = query(1, a[i] + m); //由右边开始查询,返回右边第一个大于 a[i] + m值的位置
50         if(ans == -1 || ans <= i)
51             ANS[i] = -1;
52         else if(ans > i)
53             ANS[i] = ans - i - 1;
54     }
55     printf("%d", ANS[1]);
56     for(int i = 2; i <= n; i ++)
57         printf(" %d", ANS[i]);
58     printf("
");
59     return 0;
60 }
View Code
原文地址:https://www.cnblogs.com/yuanweidao/p/11493458.html