HDU 6406 Taotao Picks Apples (线段树)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37632935/article/details/81984014

题意:给出n个苹果树的高度,taotao从第一个苹果开始摘苹果,他只能摘当前高度大于前面所有苹果树的苹果。

若干次查询每次他会问你如果把第q颗树的苹果高度改为p,他可以摘多少苹果。

思路:维护两个数组,pre从1位置到i能摘多少苹果,back记录从i位置开始到结尾能摘多少苹果。第一个数组很好维护,第二个数组我们需要找前面第一个大于他的位置,那么就涉及到区间最值查询,可以用线段树解决。

维护好这两个数组后,答案初值赋值为pre[q-1],每次查询把q位置修改为p,查询[1,q-1]最大数p的位置pos,然后比较a[pos]和p的大小,如果a[pos]<p那么ans++,那么[1,q]区间就解决了,还剩下[q+1,n]区间,q位置之后对答案有贡献的苹果树的高度肯定都是大于p的,我们查询第一个大于p的位置pos,back[pos]就是后一部分的答案。注意特判1和n的位置。

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=1e5+10;

int a[maxn],tree[maxn<<2],pre[maxn],back[maxn],pos;
int n;
void build(int l,int r,int k)
{
	if(l==r)
	{
		tree[k]=a[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,k<<1);
	build(mid+1,r,k<<1|1);
	tree[k]=max(tree[k<<1],tree[k<<1|1]);
	return ;
}
void query_max(int L,int R,int l,int r,int k) //区间最值位置 
{
	if(L==R)
	{
		//printf("--%d\n",L);
		if(a[pos]<a[L]) pos=L;
		return ;
	}
	int mid=(L+R)>>1;
	if(l<=L&&r>=R)
	{
		if(tree[k<<1]>=tree[k<<1|1]) query_max(L,mid,l,r,k<<1);
		else query_max(mid+1,R,l,r,k<<1|1);
		return ;
	}
	if(r>mid) query_max(mid+1,R,l,r,k<<1|1);
	if(l<=mid) query_max(L,mid,l,r,k<<1);
}
void query_first(int L,int R,int l,int r,int k,int v) //区间第一个大于v的位置. 
{
	if(L==R)
	{
		pos=min(pos,L);return ;
	}
	int mid=(L+R)>>1;
	if(l<=L&&r>=R)
	{
		if(tree[k<<1]>v) query_first(L,mid,l,r,k<<1,v);
		else if(tree[k<<1|1]>v) query_first(mid+1,R,l,r,k<<1|1,v);
		return ;
	}
	if(r>mid&&tree[k<<1|1]>v) query_first(mid+1,R,l,r,k<<1|1,v);
	if(l<=mid&&tree[k<<1]) query_first(L,mid,l,r,k<<1,v);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		int ma=-1;
		for(int i=1;i<=n;i++)
		{
			pre[i]=pre[i-1];
			if(a[i]>ma)pre[i]++;
			ma=max(ma,a[i]);
		}
		build(1,n,1);
		for(int i=n;i>=1;i--)
		{
			pos=INF;
			query_first(1,n,i,n,1,a[i]);
			if(pos==INF) back[i]=1;
			else back[i]=back[pos]+1;
		}
		while(m--)
		{
			int ans=1;int p,q;
			scanf("%d%d",&p,&q);
			pos=1;
			if(p!=1){
				query_max(1,n,1,p-1,1);
				ans=pre[p-1];
				if(q>a[pos]) ans++;
				else q=a[pos];
			}
			//printf("%d %d\n",pos,q);
			pos=INF;
			if(p!=n)
			query_first(1,n,p+1,n,1,q);
			if(pos!=INF) ans+=back[pos];
			printf("%d\n",ans);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37632935/article/details/81984014