51nod 3111树状数组(树状数组求max)小明爱拦截

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 3111树状数组(树状数组求max)小明爱拦截相关的知识,希望对你有一定的参考价值。

小明爱拦截

51nod 3111 小明爱拦截


题目


输入样例

8
300 207 155 300 299 170 158 65

输出样例

6

解题思路

先浅想一下DP
设 f[i] 为以 i 点结尾的最长不上升序列的长度
dp[i] = max(dp[j])+1(1 ≤ j<i 且 high[j] ≥ high[i])
O(n^2)属实不行

考虑怎么套进树状数组中🤔
j:树状数组的插入刚好可以满足两个条件,可以查询到比当前插入位小(1 ≤ j<i)且比当前位大的数(high[j] ≥ high[i])
max(dp[j]):将树状数组的存储改为max

如何满足
查询到比当前插入位小(1 ≤ j<i):树状数组按照位置查询前面的,比如4查询23,6查询45,8查询467
比当前位大的数(high[j] ≥ high[i]):这个可以先排序,从大到小的高度插入,保留原本的位置id
因为插入的位置是id,所以依然满足第一个条件


Code

#include <bits/stdc++.h>
#define ll long long
#define N 200000

using namespace std;

pair<ll, ll> a[N + 100];
ll n, t[N + 100];

ll lowbit(ll x)  return (x & -x); 

void add(ll x, ll y) 
	for(; x <= n; x += lowbit(x)) 
		if(t[x] < y) t[x] = y;
			else break;


ll sum(ll x) 
	ll ans = 0;
	for(; x; x -= lowbit(x))
		ans = max(ans, t[x]);
	return ans;


bool cmp(pair<ll, ll>k, pair<ll, ll>l) 
	if(k.first != l.first) return k.first > l.first;
	return k.second < l.second;


int main() 
	scanf("%lld", &n);
	for(int i = 1; i <= n; i ++) 
		scanf("%lld", &a[i].first);
		a[i].second = i;
	
	sort(a + 1, a + 1 + n, cmp);  //从大到小排
	for(int i = 1; i <= n; i ++) 
		ll x = a[i].second;
		add(x, sum(x) + 1);  //sum(id)为max(dp[j])
	
	printf("%lld", sum(n));
 

以上是关于51nod 3111树状数组(树状数组求max)小明爱拦截的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1286 三段子串(树状数组+拓展kmp)

51nod 第K大区间2(二分+树状数组)

51nod 3174树状数组堆积木

51nod 1107(树状数组逆序数)

51nod 1290 Counting Diff Pairs | 莫队 树状数组

51nod_1199 树的先跟遍历+区间更新树状数组