欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HDU 6406 Taotao Picks Apples(线段树)

程序员文章站 2022-05-27 15:18:00
...

Taotao Picks Apples

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2124    Accepted Submission(s): 678


 

Problem Description

There is an apple tree in front of Taotao's house. When autumn comes, n apples on the tree ripen, and Taotao will go to pick these apples.

When Taotao picks apples, Taotao scans these apples from the first one to the last one. If the current apple is the first apple, or it is strictly higher than the previously picked one, then Taotao will pick this apple; otherwise, he will not pick.

Given the heights of these apples h1,h2,⋯,hn, you are required to answer some independent queries. Each query is two integers p,q, which asks the number of apples Taotao would pick, if the height of the p-th apple were q (instead of hp). Can you answer all these queries?

 

 

Input

The first line of input is a single line of integer T (1≤T≤10), the number of test cases.

Each test case begins with a line of two integers n,m (1≤n,m≤105), denoting the number of apples and the number of queries. It is then followed by a single line of n integers h1,h2,⋯,hn (1≤hi≤109), denoting the heights of the apples. The next m lines give the queries. Each of these m lines contains two integers p (1≤p≤n) and q (1≤q≤109), as described in the problem statement.

 

 

Output

For each query, display the answer in a single line.

 

 

Sample Input

1

5 3

1 2 3 4 4

1 5

5 5

2 3

 

 

Sample Output

1

5

3

Hint

For the first query, the heights of the apples were 5, 2, 3, 4, 4, so Taotao would only pick the first apple. For the second query, the heights of the apples were 1, 2, 3, 4, 5, so Taotao would pick all these five apples. For the third query, the heights of the apples were 1, 3, 3, 4, 4, so Taotao would pick the first, the second and the fourth apples.

 

 

Source

2018 Multi-University Training Contest 8

 

 

Recommend

chendu   |   We have carefully selected several similar problems for you:  6425 6424 6423 6422 6421 

 

【思路】

题目要求必取第一个苹果且让取的苹果高度递增的最多苹果数量。

线段树可做,维护每个区间必取左端点的最长递增子序列的长度T、区间最大值M,每次问询的答案正是T[1]。易知T[rt]必定要取T[rt << 1],和T[rt << 1 | 1]中起点大于M[rt << 1]的部分,后者我们可以递归来求。

递归求一个区间rt中起点大于v的最长递增子序列长度T的方式,分两类:

若M[rt << 1] <= v,则递归右半区间求之;

若M[rt << 1] > v,则递归左半区间再加上T[rt] - T[rt << 1]得之。

单点修改操作后逐层往上更新T,总时间复杂度是HDU 6406 Taotao Picks Apples(线段树)的。

 

【代码】

//******************************************************************************
// File Name: 1010.cpp
// Author: Shili_Xu
// E-Mail: [email protected]
// Created Time: 2018年08月20日 星期一 21时17分21秒
//******************************************************************************

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;

const int MAXN = 1e5 + 5;

int t, n, m;
int h[MAXN], mx[MAXN << 2], vl[MAXN << 2], l[MAXN << 2], r[MAXN << 2];

int calc(int v, int rt)
{
	if (l[rt] == r[rt]) return (v < mx[rt]);
	if (mx[rt << 1] <= v)
		return calc(v, rt << 1 | 1);
	else
		return calc(v, rt << 1) + (vl[rt] - vl[rt << 1]);
}

void update(int rt)
{
	mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
	vl[rt] = vl[rt << 1] + calc(mx[rt << 1], rt << 1 | 1);
}

void build(int left, int right, int rt)
{
	l[rt] = left, r[rt] = right;
	if (left == right) {
		mx[rt] = h[left];
		vl[rt] = 1;
		return;
	}
	int mid = (left + right) >> 1;
	build(left, mid, rt << 1);
	build(mid + 1, right, rt << 1 | 1);
	update(rt);
}

void modify(int pos, int num, int rt)
{
	if (l[rt] == r[rt]) {
		mx[rt] = num;
		return;
	}
	int mid = (l[rt] + r[rt]) >> 1;
	if (pos <= mid) modify(pos, num, rt << 1);
	if (pos >= mid + 1) modify(pos, num, rt << 1 | 1);
	update(rt);
}

int main()
{
	scanf("%d", &t);
	while (t--) {
		scanf("%d %d", &n, &m);
		for (int i = 1; i <= n; i++) scanf("%d", &h[i]);
		build(1, n, 1);
		while (m--) {
			int x, y;
			scanf("%d %d", &x, &y);
			modify(x, y, 1);
			printf("%d\n", vl[1]);
			modify(x, h[x], 1);
		}
	}
	return 0;
}