2019 徐州网络赛 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 n1⋯n from left to right.

蔡徐坤,是一个篮球队的队长,正在指导对n个队员的训练。他让所有成员占成一行,并且从左往右从1开始标号。

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+mwj​≥wi​+m.

第i个人的能力值是wi,如果他右边有个人的能力值不小于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−1 .

我们定义第i个人的愤怒值是他与那些令他愤怒的人之间的某个人所间隔的最长距离,如果没人使得他不高兴,就输出-1

Please calculate the anger of every team member .

请计算出每个人的愤怒值。

本题可以用线段树维护每个区间的最大值,然后在查询某个值对应的答案时默认从右子树开始查找答案,如果存在的话(贪心),查询会返回相应的位置索引值。

比如样例3 4 5 6 2 10,如果要查询3的对应答案,从根节点开始(根节点保存了全区间最大值:10),发现右子树([4,6]区间)的最大值不小于3,于是直接向右查询,又发现[5,6]区间的最大值不小于3,继续向右查询,直至找到答案。如果右子树有合理答案,即使左子树存在这样的答案也无需去查询,因为题干中要求的是最长的距离,所以总是可以从右往左来找。

//#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define DETERMINATION main
#pragma GCC optimize(2)
#pragma warning(disable:4996)
#define lldin(a) scanf("%lld", &a)
#define println(a) printf("%lld\n", a)
#define print(a) printf("%lld ", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<
//inline BigInteger nextBigInteger()
//{
//    BigInteger tmp = 0, si = 1;char c;    c = getchar();
//    while (!isdigit(c))
//{if (c == '-')si = -1;c = getchar();}
//    while (isdigit(c))
//    {tmp = tmp * 10 + c - '0';c = getchar();}
//    return si * tmp;    
//}            
//std::ostream& operator<<(std::ostream& os, __int128 T)
//{
//    if (T<0) os<<"-";if (T>=10 ) os<0 ? (int) (T%10) : -(int) (T%10) ) ;
//}
//void output(BigInteger x)
//{
//    if (x < 0)
//    {x = -x;putchar('-');}
//    if (x > 9) output(x / 10);
//    putchar(x % 10 + '0');
//    }
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
ll arr[959996];
struct node
{
	ll left, right, value;
}nodes[5*100000*4];
void construction(ll current, ll left, ll right)
{
	nodes[current].left = left, nodes[current].right = right;
	if (left == right)
	{
		nodes[current].value = arr[left];
		return;
	}
	ll mid = (left + right) >> 1;
	construction(current << 1, left, mid);
	construction(current << 1 | 1, mid + 1, right);
	nodes[current].value = max(nodes[current << 1].value, nodes[current << 1 | 1].value);
	return ;
}
ll query(ll current, ll target)
{
	if (nodes[current].left == nodes[current].right)
		return nodes[current].left;
	if (nodes[current << 1 | 1].value >= target)
		return query(current << 1 | 1, target);
	else if (nodes[current << 1].value >= target)
		return query(current << 1, target);
	else
		return -1;
}
ll res[599999];
int DETERMINATION()
{
	//ios::sync_with_stdio(false);
	//cin.tie(0),cout.tie(0)
	ll n, m;
	lldin(n), lldin(m);
	for (int i = 1; i <= n; i++)
		lldin(arr[i]);
	construction(1, 1, n);
	for (int i = 1; i <= n; i++)
	{
		int tmpans = query(1, arr[i] + m);
		if (tmpans == -1 || tmpans < i)
			res[i] = -1;
		else
			res[i] = tmpans - i - 1;
	}
	for (int i = 1; i <= n; i++)
	{
		if (i != n)
			printf("%lld ", res[i]);
		else
			printf("%lld\n", res[i]);
	}
	return 0;
}

 

你可能感兴趣的:(数据结构-线段树)