zoukankan      html  css  js  c++  java
  • hdu 4521 小明系列问题——小明序列 线段树

    题意:

    给你一个长度为n的序列v,你需要输出最长上升子序列,且要保证你选的两个相邻元素之间在原数组中的位置之差大于d

    题解:

    这个就是原来求最长上升子序列的加强版,这个思路和最长上升子序列的差不多

     

    设dp[i]:截至到位置i能找到的最长上升子序列

    对于一个位置i,我们要找截至到它的最长上升子序列,就需要for循环寻找dp[j]的最大值(且v[j]<v[i] 而且 1<=j<=i-1)

    我们可以使用线段树来维护dp[j]的最大值

    但是你发现dp[1],dp[2]...dp[i-1]中可能有某个位置k(1<=k<=i-1)满足,v[k]>v[i],那么dp[k]我们就不可以去维护这个值

    我们怎么解决这个问题?

    我们可以按照v[k]的值把它的dp[k]放在线段树中的位置v[k]位置,这样就可以避免这个问题

    代码:

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    const int INF=0x3f3f3f3f;
    #define rt root
    #define ls root<<1
    #define rs (root<<1)|1
    #define mem(a) memset(a,0,sizeof(a))
    #define mem_(a) memset(a,-1,sizeof(a))
    #define mem__(a) memset(a,INF,sizeof(a))
    typedef long long ll;
    int tree[maxn<<2],arr[maxn],len[maxn];
    int n,d;
    struct shudui
    {
        int val,id;
    } m[maxn];
    bool mmp(shudui x,shudui y)
    {
        if(x.val!=y.val)
            return x.val<y.val;
        return x.id>y.id;
    }
    void push_up(int root)
    {
        tree[rt]=max(tree[ls],tree[rs]);
    }
    void update(int root,int L,int R,int pos,int val)
    {
        if(L==R)
        {
            tree[rt]=val;
            return;
        }
        int mid=(L+R)>>1;
        if(pos<=mid) update(ls,L,mid,pos,val);
        else update(rs,mid+1,R,pos,val);
        push_up(rt);
    }
    int query(int root,int L,int R,int LL,int RR)
    {
        if(LL<=L && R<=RR)
        {
            return tree[rt];
        }
        int mid=(L+R)>>1,ans=0;
        if(LL<=mid) ans=max(ans,query(ls,L,mid,LL,RR));
        if(RR>mid) ans=max(ans,query(rs,mid+1,R,LL,RR));
        return ans;
    }
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        int i,j,k,n;
        while(cin>>n>>k)
        {
            mem(tree);
            memset(len,0,sizeof(len));
            int mx=-1;
            for(i=1; i<=n; i++)
            {
                cin>>arr[i];
                if(arr[i]>mx)mx=arr[i];
            }
            mx++;
            int ans=0;
            for(i=1; i<=n; i++)
            {  //这个arr[i-k-1]+1就是为了保证严格上升子序列
                if(i-k-1>0)update(1,1,mx,arr[i-k-1]+1,len[i-k-1]);
                if(arr[i]!=0)len[i]=query(1,1,mx,1,arr[i])+1;//arr[i]==0时查找会出现错误111111111111155t
                else len[i]=1;
                if(len[i]>ans)ans=len[i];
            }
            cout<<ans<<endl;
        }
    }
    /*
    5 0
    3 1 5 2 3
    
    len1=1
    
    U 4 1
    Q 1 1 1
    len2=2
    
    U 2 2
    Q 1 5 3
    len3=3
    */
  • 相关阅读:
    动画,缩放
    本地公司
    调研 公司信息
    外贸 内贸 经商
    情感 爱情 恋爱
    H5源码
    世界 生活
    标识
    Jackson
    java数据结构
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13704952.html
Copyright © 2011-2022 走看看