Taotao Picks Apples
HDU 6406 Taotao Picks Apples
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?
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.
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
题意:给出苹果树的高度,然后对于每次查询将某个位置苹果树的高度改变,问可以摘多少苹果,淘淘摘苹果时,淘淘将这些苹果从第一个苹果扫到最后一个。如果当前的苹果是第一个苹果,或者它严格高于之前选择的苹果,那么淘淘将采摘这个苹果; 否则,他不会选择。
题解:
单调栈 + 二分
看到这道题的时候,很明显想到单调栈,然后我们队维护从前到后的单调栈,本来想对于某个位置,他前面的可以根据这个栈求出,但后面想二分这个单调栈解决,最后发现并不可行,因为当某个位置的高度变低可能影响结果。画个图:
![](https://images2018.cnblogs.com/blog/1301190/201808/1301190-20180816090014675-1115513033.png)
然后想到可以维护后面的单调栈,前面的可以预处理,maxx[i] 表示 1 -> i的最大值,pre[i] 表示 1 -> i 摘得苹果,后面维护从大到小的栈,但应该提前将位置排序(为什么排序? 排序为了我们只想研究 pos+1 -> 后面的问题,然后用这个栈在维护前面的)然后答案就是pre[pos - 1] + (maxx[pos - 1] < val ? 1 : 0) + 二分后面的栈中大于max(val,maxx[pos - 1])的位置 + 1
说的有点不明白,请看下代码,有问题可以留言,便于改正
c++ code:
#include <bits/stdc++.h> // author by LK-AC using namespace std; const int N = 1e5 + 10; int pre[N],stadown[N],down,a[N],ans[N],maxx[N]; struct Node{ int pos,val,id; }node[N]; int cmp(Node a,Node b){ return a.pos > b.pos; } int upper(int val) // 二分找到单调栈中大于val 的位置 + 1 { int l = 0,r = down - 1,pos = -1; while(l <= r) { int mid = (l+r)>>1; if(stadown[mid] > val) { pos = mid; l = mid + 1; } else r = mid - 1; } return pos+1; } int main() { int t; scanf("%d",&t); while(t--) { int n,m; down = 0; scanf("%d%d",&n,&m); maxx[0] = pre[0] = 0; for(int i = 1;i <= n;i++) { scanf("%d",a+i); if(i == 1) maxx[i] = a[i],pre[i] = 1; else { if(maxx[i-1] < a[i]) { maxx[i] = a[i]; pre[i] = pre[i-1]+1; } else{ pre[i] = pre[i-1]; maxx[i] = maxx[i-1]; } } } for(int i = 1;i <= m;i++) { scanf("%d%d",&node[i].pos,&node[i].val); node[i].id = i; } sort(node+1,node+1+m,cmp); // 排序将位置离散化 int r = n; for(int i = 1;i <= m;i++) { int pos = node[i].pos,val = node[i].val; while(r > pos) // 维护单调栈,二分插入 { if(down == 0) stadown[down++] = a[r]; else { down = upper(a[r]); stadown[down++] = a[r]; } r--; } int ant = pre[pos - 1],maxx1; if(maxx[pos - 1] > val) maxx1 = maxx[pos - 1]; else if(maxx[pos - 1] < val) maxx1 = val,ant++; // cout<<"maxx1:"<<maxx1<<" ant:"<<ant<<endl; pos = upper(maxx1); ant += max(0,pos); ans[node[i].id] = ant; } for(int i = 1;i <= m;i++) printf("%d\n",ans[i]); } return 0; }