Taotao Picks Apples HDU - 6406(线段树求最长上升子序列)

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.
对于一段可更改的序列,求它的最长上升子序列。
一般习惯dp求最长上升子序列,二分优化之后是O(nlogn)的时间复杂度。但是这个是带修改的序列,一般这种单点修改的序列一般会想到线段树(dp+二分的方法我也不知道行不行)。我们用线段树维护每一段的最大值,以及这一段上升序列的长度。在向上更新的时候去更新上升序列的长度。
在这里插入图片描述
对于整个区间内能摘到多少苹果。我们分成[l,mid]和[mid+1,r]来讨论。如果[l,mid]内的值大于[mid+1,r]的值,那么后面区间的苹果必定无法摘到。所以整个区间内的苹果总数最少是这个区间左儿子的区间苹果数。右儿子的区间能摘多少苹果就根据左儿子的最大值去更新。
对于上面二叉树来说,1号节点的答案值肯定是2号节点的答案值+3号节点的贡献值。
①如果2号节点的最大值v大于3号节点的最大值,那么2号节点的答案就是4号节点的答案。
②如果2号节点的最大值v小于3号节点的最大值,那么递归找3号区间内符合的区间。如果6号节点的最大值小于v,那么这个值对于答案贡献为0,直接去找7号节点就行。
③接着②来,如果6号节点的最大值大于v, 那么7号节点对于答案的贡献可以直接求到(p[cur].cnt-p[cur<<1].cnt),不能直接用p[cur<<1|1].cnt,因为这个p[cur<<1|1].cnt是7号节点独立的,没有考虑到6号节点。但是p[cur].cnt-p[cur<<1].cnt是考虑之后的结果,这样保证了p[cur].cnt-p[cur<<1].cnt代表着7号区域比6号区域大的值的数。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=1e5+100;
struct node{
	int l;
	int r;
	int cnt;
	int _max;
}p[maxx<<2];
int a[maxx];
int n,m;

inline int query(int cur,int v)
{
	int L=p[cur].l;
	int R=p[cur].r;
	if(L==R) return p[cur]._max>v;//到达了叶子节点
	if(p[cur<<1]._max<=v) return query(cur<<1|1,v);//左儿子的最大值小于v,直接看右儿子
	else return p[cur].cnt-p[cur<<1].cnt+query(cur<<1,v);//否则就直接求出右儿子的贡献值,然后探究左儿子。
}
inline void pushup(int cur)
{
	p[cur]._max=max(p[cur<<1]._max,p[cur<<1|1]._max);
	p[cur].cnt=p[cur<<1].cnt+query(cur<<1|1,p[cur<<1]._max);/更新最长上升子序列
}
inline void build(int l,int r,int cur)
{
	p[cur].l=l;
	p[cur].r=r;
	p[cur]._max=0;
	if(l==r)
	{
		p[cur]._max=a[l];
		p[cur].cnt=1;
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,cur<<1);
	build(mid+1,r,cur<<1|1);
	pushup(cur);
}
inline void update(int pos,int v,int cur)
{
	int L=p[cur].l;
	int R=p[cur].r;
	if(L==R)
	{
		p[cur]._max=v;
		return ;
	}
	int mid=L+R>>1;
	if(pos<=mid) update(pos,v,cur<<1);
	else update(pos,v,cur<<1|1);
	pushup(cur);
}
int main()
{
	int t,x,y;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		build(1,n,1);
		while(m--)
		{
			scanf("%d%d",&x,&y);
			update(x,y,1);
			printf("%d\n",p[1].cnt);
			update(x,a[x],1);
		}
	}
	return 0;
}

努力加油a啊,(o)/~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值