zoukankan      html  css  js  c++  java
  • 51nod 1376【线段树维护区间最大值】

    引自:wonter巨巨的博客

    定义 dp[i] := 以数字 i(不是下标 i)为结尾的最长上升长度

    然后用线段树维护 dp[i]:
    每个节点维护 2 个信息,一个是当前区间的最大上升长度,一个是最大上升长度的方案数,


    这里再详细说下这篇题解。。。也是弱弱自己的理解吧。。。
    以1-n的值为线段树所代表的区间;
    然后依次更新,题目就是要找上升序列,那么我们只要每次查询0~arr[i]-1范围内最长的那个长度和方案拿出来;
    然后再去0到n区间里更新,更新的值是arr[i],长度为查询到的x+1,方案还是查询到的方案y;


    具体查询:

    我们是想知道在一段区间(从0到值arr[i]-1,这里一定要注意是值!是值!)的最长长度;

    所以一直查询到那个区间,然后一直下去就好了;
    中间如果出现被mid是夹在被查询区间中间的话,就要比较一下左右两段区间的最长长度


    具体更新:
    一直要先更新到最底;
    然后再往上更新,

    往上更新只要比较一下左右子区间的长度就好了;

    #include <bits/stdc++.h>
    using namespace std;
    const int N=5e5+10;
    const int mod=1e9+7;
    
    
    struct asd{
        int left,right,mid;
        int val;
        int cnt;
    };
    asd q[N*4];
    
    void build(int i,int left,int right)
    {
        q[i].left=left;
        q[i].right=right;
        q[i].mid=(left+right)>>1;
        q[i].cnt=q[i].val=0;
        if(left==right)
            return;
        build(i*2,left,q[i].mid);
        build(i*2+1,q[i].mid+1,right);
    }
    
    void query(int i, int left, int right, int &x, int &y )
    {
        if(q[i].left==left&&q[i].right==right)
        {
            x=q[i].val;
            y=q[i].cnt;
            return;
        }
        if(right<=q[i].mid)
        {
            query(i*2, left, right, x, y);
            return;
        }
        if(left>q[i].mid)
        {
            query(i*2+1,left,right, x, y);
            return;
        }
        int lx,ly;
        int rx,ry;
        query(i*2,left,q[i].mid,lx,ly);
        query(i*2+1,q[i].mid+1,right, rx,ry);
        if(lx==rx)
        {
            x=lx;
            y=(ly+ry)%mod;
        }
        else if(lx>rx)
        {
            x=lx;
            y=ly;
        }
        else
        {
            x=rx;
            y=ry;
        }
    }
    
    void update(int i,int p,int x,int y)
    {
        if(q[i].left==q[i].right&&q[i].left==p)
        {
            if(x>q[i].val)
            {
                q[i].val=x;
                q[i].cnt=y;
            }
            else if(x==q[i].val)
            {
                q[i].cnt=(q[i].cnt+y)%mod;
            }
            return;
        }
        if(p<=q[i].mid)
            update(i*2,p,x,y);
        else if(p>q[i].mid)
            update(i*2+1,p,x,y);
        if(q[i*2].val==q[i*2+1].val)
        {
            q[i].val=q[i*2].val;
            q[i].cnt=(q[i*2].cnt+q[i*2+1].cnt)%mod;
        }
        else if(q[i*2].val>q[i*2+1].val)
        {
            q[i].val=q[i*2].val;
            q[i].cnt=q[i*2].cnt;
        }
        else
        {
            q[i].val=q[i*2+1].val;
            q[i].cnt=q[i*2+1].cnt;
        }
    }
    
    
    int n;
    int arr[N];
    vector<int>xs;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&arr[i]);
            xs.push_back(arr[i]);
        }
        sort(xs.begin(),xs.end());
        auto e=unique(xs.begin(),xs.end());
        for(int i=1;i<=n;i++)
            arr[i]=lower_bound(xs.begin(), e, arr[i])-xs.begin()+1;
    
        build(1,0,n);
    
        for(int i=1;i<=n;i++)
        {
            int x,y;
            query(1,0,arr[i]-1,x,y);
    //        printf("%d %d
    ",x,y);
            if(!y)
                y=1;
            update(1, arr[i] , x+1, y);
        }
        int x,y;
        query(1,0,n,x,y);
        printf("%d
    ",y);
        return 0;
    }
    
    


  • 相关阅读:
    区别TPS QPS HPS RPS PV UV
    C/C++常用库及工具
    CentOS常用命令备忘
    PHP的学习--Traits新特性
    CentOS7创建本地YUM源的三种方法
    CentOS下iptables详解
    Linux备份压缩命令
    Nginx HTTPS功能部署实践
    Fuel 30 分钟快速安装OpenStack
    hadoop学习通过虚拟机安装hadoop完全分布式集群
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6216770.html
Copyright © 2011-2022 走看看