2019icpc 徐州网络赛 E.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⋯n from left to right.
The ability of the i-th person is w_i, and if there is a guy whose ability is not less than w_i+m stands on his right, he will become angry. It means that the j-th person will make the i-th person angry if j>i and wj ≥ wi +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 −1 .
Please calculate the anger of every team member .

Input
The first line contains two integers n and m(2≤n≤5∗10^5, 0≤m≤10^9) .
The following line contain nn integers w_1…w_n(0≤wi≤10^9) .

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
题意:给定n个数,与一个数m,求ai右边最后一个至少比ai大m的数与这个数之间有多少个数
传送门
solution:用线段树来存储每个区间的最大值,如此,便达到了二分的时间复杂度

#include <bits/stdc++.h>
using namespace std;

int a[1000005];
struct node{
	//意思是在[l, r]区间中最大的数是maxele
	int l, r, maxele;
}tree[4000010];

void build(int l, int r, int p)
{
	tree[p].l = l;
	tree[p].r = r;
	if (l == r){
		tree[p].maxele = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(l, mid, p << 1);
	build(mid + 1, r,  p << 1 | 1);
	tree[p].maxele = max(tree[p << 1].maxele, tree[p << 1 | 1].maxele);
}

int query(int l, int r, int p){
	if (l == tree[p].l && r == tree[p].r)return tree[p].maxele;
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (l > mid)return query(l, r, p << 1 | 1);
	else if (r <= mid)return query(l, r, p << 1);
	else return max(query(l, mid, p << 1), query(mid + 1, r, p << 1 | 1));
}

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i)scanf("%d", &a[i]);
	build(1, n, 1);
	for (int i = 1; i < n; ++i)
	{
		int s = m + a[i], l = i + 1, r = n;
		while (l < r){
			int mid = (l + r + 1) >> 1;
			if (query(mid, r, 1) >= s)l = mid;
			else if (query(l, mid, 1) >= s)r = mid - 1;
			else break;
		}
		if (a[l] >= s)printf("%d ", l - i - 1);
		else printf("-1 ");
	}
	printf("-1\n");
	return 0;
}
上一篇:Basketball Exercise


下一篇:print 高级用法