zoukankan      html  css  js  c++  java
  • bzoj3173: [Tjoi2013]最长上升子序列(二分+树状数组)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3173

    插入的数是以递增的顺序插入的

    这说明如果倒过来考虑,那么从最后一个插入的开始删除,不会对以某个数结尾的最长上升子序列产生影响

    所以 先原序列求出来,输出即可

    还原原序列的方法:

    可以用平衡树,dfs序就是原序列

    嫌麻烦,不想写,所以  树状数组

    假设最后一个数是n,插入位置是y,

    倒数第二个数是n-1,插入位置是x

    那么y就是n的最终位置

    如果y在x后面,那么x就是n-1的最终位置

    如果y在x前面,那么x+1就是n-1的最终位置

    所以 如果倒序插入每个数,

    若数m的插入位置为p,

    数m的最终位置就是当前序列 的 第p个空位

    这可以二分+树状数组确定 数m的位置 

    注意求LIS时,求出的f[i] 时 以i结尾的LIS

    要求回答 序列的LIS,所以要跟f[i-1]取大

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 100001
    
    #define lowbit(x) x&-x
    
    int n;
    int p[N];
    
    int c[N];
    
    int a[N];
    int dp[N],m;
    int f[N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
        
    void add(int pos,int x)
    {
        while(pos<=n)
        {
            c[pos]+=x;
            pos+=lowbit(pos);
        }
    }
    
    int query(int x)
    {
        int sum=0;
        while(x)
        {
            sum+=c[x];
            x-=lowbit(x);
        }
        return sum;
    }
    
    int find(int x)
    {
        int l=1,r=n,mid,tmp;
        while(l<=r)
        {
            mid=l+r>>1;
            if(mid-query(mid)>=x) tmp=mid,r=mid-1;
            else l=mid+1;
        }
        return tmp;
    }
    
    void init()
    {
        read(n);
        for(int i=1;i<=n;++i) read(p[i]);
        int pos;
        for(int i=n;i;--i)
        {
            pos=find(p[i]+1);
            a[pos]=i;
            add(pos,1);
        }
    }
    
    void pre_LIS()
    {
        dp[m=1]=a[1];
        f[a[1]]=1;
        int pos;
        for(int i=2;i<=n;++i)
        {
            if(a[i]>dp[m]) 
            {
                dp[++m]=a[i];
                f[a[i]]=m;
            }    
            else
            {
                pos=lower_bound(dp+1,dp+m+1,a[i])-dp;
                if(a[i]<dp[pos]) dp[pos]=a[i];
                f[a[i]]=pos;
            }
        }
    }
    
    
    void solve()
    {
        int now=0; 
        for(int i=1;i<=n;++i) 
        {
            now=max(now,f[i]);
            printf("%d
    ",now);
        }
    }
    
    int main()
    {
        init();
        pre_LIS();
        solve();
    }
  • 相关阅读:
    document.createElement在IE和Firefox下的差异
    css3:基础知识
    XMLTProcessor根据XSLT样式规则将节点转换为document对象
    Sql:查看数据库表和表结构的语句
    前端性能优化方法总结
    vue-resource 设置请求的参数以formData形式以及设置请求的过滤器
    vuex
    vue 随笔3
    vuex
    vue随笔2
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8978474.html
Copyright © 2011-2022 走看看