• 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
  • 相关阅读:
    grep 命令操作
    vi & vim复制,粘贴,剪切文本
    β版本第四次冲刺
    β版本第三次冲刺
    β版本第二次冲刺
    β版本第一次冲刺
    华为软件开发云,个人评测及体会
    事后诸葛亮
    【Alpha】团队课程展示
    团队Alpha博客链接目录
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/11493458.html
Copyright © 2020-2023  润新知