【补档】【洛谷p1020】树状数组题解

  先附一篇以前的文章链接:https://blog.csdn.net/PWeiDa/article/details/82226758

  现在来补一下这题的树状数组方法

  有可能有人不是很明白树状数组的原理,今天找到一篇大佬写的通俗易懂的博客,给个链接

  大佬博客:https://www.cnblogs.com/acgoto/p/8583952.html#4044998

  现在明白树状数组了,再来看看怎么运用在这题上,这题是为了求最长上升子序列和最长不上升子序列,最重要的就是快速维护栈中数据,所以可以用树状数组来存数据,不过和之前存系统高度不一样,这里存的是在每个导弹被拦截时的最长长度

代码如下:

#include <iostream>
#include <string.h>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <stack>
#include <queue>
#include <sstream>
#include <vector>
#include <set>

using namespace std;

int f[100005],a[100005];
int maxn;

int lowbit(int x)
{
    return x&(-x);
}

void add(int x,int u)
{
    for(int i=x;i<=maxn;i+=lowbit(i))
    f[i]=max(f[i],u);
}

int find(int x)
{
    int ans=0;
    for(int i=x;i>=1;i-=lowbit(i))
    ans=max(ans,f[i]);
    return ans;
}

int main()
{
    int n=0;
    maxn=0;
    while(scanf("%d",&a[++n])!=EOF)
    {
        maxn=max(maxn,a[n]);
    }
    n--;
    int ans1=0,ans2=0;
    for(int i=n;i>=1;i--)
    {
        int u=find(a[i])+1;//这里是大于
        add(a[i],u);
        ans1=max(ans1,u);
    }
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        int u=find(a[i]-1)+1;//这里是小于,不能等于,原因可以看之前的代码
        add(a[i],u);
        ans2=max(ans2,u);
    }
    printf("%d\n",ans1);
    printf("%d\n",ans2);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/PWeiDa/article/details/82288482