Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1862 Accepted Submission(s): 580
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
思路:一开始读错题了,以为是找从第一个数开始的最长上升子序列,到最后才发现是遇到一个比上一个大的就摘掉,线段树解法是先预处理出来两个数组d1,d2,d1[i]数组里存的是从第1到a[i]能摘的苹果,这个比较好处理,d2[i]数组里存的是从a[i]到a[n]能摘的苹果,这个稍微麻烦些,倒着遍历,每次用线段树找出a[i]之后第一个比第a[i]这个数大的的位置j,d2[i] = d2[j] + 1,每次修改查询,用线段树找出1到p-1最大的数的位置pos,ans+=d1[pos],如果q比a[pos]大的话,ans再加1,再用线段树找出p+1到n第一个比max(a[pos],q )大的数的位置pos2,ans+=d2[pos2]
#include
#define MAXN 100005
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
struct node
{
int l,r;
int Max,pos;
}tree[MAXN << 2];
int a[MAXN],d1[MAXN],d2[MAXN];
int cur;
void pushup(int num)
{
tree[num].Max = max(tree[lson].Max,tree[rson].Max);
if(tree[lson].Max >= tree[rson].Max) tree[num].pos = tree[lson].pos;
else tree[num].pos = tree[rson].pos;
}
void build(int num,int l,int r)
{
tree[num].l = l;
tree[num].r = r;
if(l == r) {
tree[num].Max = a[l];
tree[num].pos = l;
return;
}
int mid = (l + r) >> 1;
build(lson,l,mid);
build(rson,mid + 1,r);
pushup(num);
}
void query1(int num,int l,int r,int val)
{
if(tree[num].l == tree[num].r) {
if(tree[num].Max > val) cur = min(cur,tree[num].l);
return;
}
int mid = (tree[num].l + tree[num].r) >> 1;
if(tree[num].l == l && tree[num].r == r) {
if(tree[lson].Max > val) query1(lson,l,mid,val);
else if(tree[rson].Max > val) query1(rson,mid + 1,r,val);
return;
}
if(r <= mid) query1(lson,l,r,val);
else if(l > mid) query1(rson,l,r,val);
else {
query1(lson,l,mid,val);
query1(rson,mid + 1,r,val);
}
}
void query2(int num,int l,int r)
{
if(tree[num].l == l && tree[num].r == r) {
if(tree[num].Max > a[cur]) cur = tree[num].pos;
return;
}
int mid = (tree[num].l + tree[num].r) >> 1;
if(r <= mid) query2(lson,l,r);
else if(l > mid) query2(rson,l,r);
else {
query2(lson,l,mid);
query2(rson,mid + 1,r);
}
}
int main(void)
{
int T,n,m,Max,pos,val,ans;
scanf("%d",&T);
while(T--) {
memset(d1,0,sizeof(d1));
memset(d2,0,sizeof(d2));
scanf("%d %d",&n,&m);
Max = 0;
for(int i = 1; i <= n; i++) {
scanf("%d",&a[i]);
if(a[i] > Max) {
d1[i] = d1[i - 1] + 1;
Max = a[i];
}
else d1[i] = d1[i - 1];
}
build(1,1,n);
d2[n] = 1;
for(int i = n - 1; i >= 1; i--) {
cur = n + 1;
query1(1,i + 1,n,a[i]);
d2[i] = d2[cur] + 1;
}
while(m--) {
ans = cur = 0;
scanf("%d %d",&pos,&val);
if(pos != 1) query2(1,1,pos - 1);
ans += d1[cur];
if(val > a[cur]) ans++;
else val = a[cur];
cur = n + 1;
if(pos != n) query1(1,pos + 1,n,val);
ans += d2[cur];
printf("%d\n",ans);
}
}
return 0;
}
/*
1
5 3
1 2 3 4 4
1 5
5 5
2 3
*/