HDU 6406 Taotao Picks Apples 预处理+二分

本文介绍了一道关于序列处理的算法题,通过预处理和二分查找的方法解决了一个有趣的摘苹果问题。题目要求计算在特定条件下可以摘取的苹果数量,并针对不同的查询条件给出解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Taotao Picks Apples

There is an apple tree in front of Taotao's house. When autumn comes, nn 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,⋯,hnh1,h2,⋯,hn , you are required to answer some independent queries. Each query is two integers p,qp,q , which asks the number of apples Taotao would pick, if the height of the pp -th apple were qq (instead of hphp ). Can you answer all these queries?

Input

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

Each test case begins with a line of two integers n,mn,m (1≤n,m≤105)(1≤n,m≤105) , denoting the number of apples and the number of queries. It is then followed by a single line of nn integers h1,h2,⋯,hnh1,h2,⋯,hn (1≤hi≤109)(1≤hi≤109) , denoting the heights of the apples. The next mm lines give the queries. Each of these mm lines contains two integers pp (1≤p≤n)(1≤p≤n) and qq (1≤q≤109)(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.

题意:给你一个序列,m次修改每次修改都有依次访问,从第一个必选,后面的选的一定严格比前面的数大,知道遍历所整个序列,问一共选了多少个数。

思路:比赛的时候也想到了预处理加二分查找,代码写了差不多100行,出了很多bug,最后由于思路不严谨有个地方出错,心态炸裂,最后没有ac,面才补的,当我冷静下来的时候在仔细的思考,认真的debug终于还是过了,比赛的时候出各种状况,难受。

具体看代码:

#include<stdio.h>
#include<string.h>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<map>
#define ll long long
#define qq printf("QAQ\n");
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
const ll linf=8e18+9e17;
const int mod=1e9+7;
const double e=exp(1.0);
const double pi=acos(-1);
int a[maxn],in[maxn],inid[maxn],inmin[maxn];
vector<int>v[maxn];
int main()
{
    int t,n,m,cnt;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        cnt=1;
        inid[1]=1;
        for(int i=1;i<=n;i++)
        {
        	scanf("%d",&a[i]);
        	if(i==1)in[cnt]=a[i],v[1].clear();//记录上升的位置以及值 
        	else {
        		if(a[i]>in[cnt])in[++cnt]=a[i],inid[cnt]=i,v[cnt].clear();//记录上升的位置以及值 
        		else if(v[cnt].empty()||v[cnt][v[cnt].size()-1]<a[i])v[cnt].push_back(a[i]);//记录两个上升点执之间数的上升子序列 
			}	
		}
		int pos,data;
		while(m--)
		{
			scanf("%d%d",&pos,&data);
			int f=upper_bound(inid+1,inid+cnt+1,pos)-inid;
			int ff=upper_bound(in+1,in+cnt+1,data)-in;
			if(inid[f-1]==pos)//如果修改的正好在原序列的上升的位置上时 
			{
				if(in[f-1]<=data)//如果修改的值比原来的大 
					printf("%d\n",f+cnt-ff);
				else{
					if(f>2&&in[f-2]>data){//比上一个上升数小 
						int f2=upper_bound(v[f-1].begin(),v[f-1].end(),in[f-2])-v[f-1].begin();
						printf("%d\n",cnt-1+v[f-1].size()-f2);
					}
					else {//比上一个上升的大 
						int f1=upper_bound(v[f-1].begin(),v[f-1].end(),data)-v[f-1].begin();
						printf("%d\n",cnt-1+v[f-1].size()-f1+1);
					}					
				}
			}
			else {//否则 
				if(data<=in[f-1])printf("%d\n",cnt);
				else printf("%d\n",f-1+cnt-ff+2);				
			}
		}
    }
    return 0;
}
/*
1
9 100
1 5 3 2 8 4 5 6 9
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值