zoukankan      html  css  js  c++  java
  • 最大连续区间(HDU-1540)

    HDU1540

    线段树最大连续区间。

    给定长度为n的数组,m次操作。

    操作D,删除给定节点。

    操作R,恢复最后一个删除的节点。

    操作Q,询问给定节点的最大连续区间

    维护三个值,区间的最大左连续区间,最大右连续区间,最大连续区间

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <stack>
    using namespace std;
    typedef long long ll;
    const int maxn = 50000 + 5;
    
    #define lson l,m,st<<1
    #define rson m+1,r,st<<1|1
    
    int treelmax[maxn<<2];
    int treermax[maxn<<2];
    int len[maxn<<2]; 
    
    void build(int l,int r,int st)
    {
        len[st]=r-l+1;
        if(l==r) 
        {
            treelmax[st]=1;treermax[st]=1;
            return ;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        treelmax[st]=len[st]; //初始化的值全为区间长度
        treermax[st]=len[st];
    }
    
    void UpdataDes(int x,int l,int r,int st)  //破坏
    {
        if(l==x&&r==x)
        {
            treelmax[st]=0; treermax[st]=0;len[st]=0; return;
        }
        int m=(l+r)>>1;
        if(x<=m) UpdataDes(x,lson);
        else  UpdataDes(x,rson); //if(x>m)
        treelmax[st]=treelmax[st<<1]==(m-l+1)?treelmax[st<<1]+treelmax[st<<1|1]:treelmax[st<<1]; //判断左儿子的最大左连续区间是否等于左儿子区间长度,如果等于,那么父亲的最大左连续区间就等于左儿子的区间长度加上右儿子右最大左区间连续长度
        treermax[st]=treermax[st<<1|1]==(r-m)?treermax[st<<1|1]+treermax[st<<1]:treermax[st<<1|1];
       len[st]=max(max(treelmax[st<<1],treermax[st<<1|1]),treermax[st<<1]+treelmax[st<<1|1]);
        //父节点的最大连续长度等于 左儿子最大左连续区间 右儿子最大右连续区间 左儿子最大右连续区间加上右儿子最大左连续区间  中的最大值
    }
    
    void UpdataRec(int x,int l,int r,int st)  //修复
    {
        if(l==x&&r==x)
        {
            treelmax[st]=1; treermax[st]=1;len[st]=1; return ;
        }
        int m=(l+r)>>1;
        if(x<=m) UpdataRec(x,lson);
        else  UpdataRec(x,rson); //if(x>m)
        treelmax[st]=treelmax[st<<1]==(m-l+1)?treelmax[st<<1]+treelmax[st<<1|1]:treelmax[st<<1];
        treermax[st]=treermax[st<<1|1]==(r-m)?treermax[st<<1|1]+treermax[st<<1]:treermax[st<<1|1];
        len[st]=max(max(treelmax[st<<1],treermax[st<<1|1]),treermax[st<<1]+treelmax[st<<1|1]);
        //pushup; 
    }
    
    int query(int x,int l,int r,int st)
    {
        if(l==r||len[st]==0||len[st]==r-l+1)
        return len[st];
        int m=(l+r)>>1;
        if(x<=m)  //x在左儿子区间内
        {
            if(x>=m-treermax[st<<1]+1)  //x在左儿子的右连续区间内
            return treermax[st<<1]+treelmax[st<<1|1];  //左儿子右连续
            //return len[st<<1];
            else //x在左儿子的左连续区间内
            return query(x,lson); 
        }
        else    //x在右儿子区间内
        {
            if(x<m+1+treelmax[st<<1|1])    //x在右儿子的左连续区间
            return treermax[st<<1]+treelmax[st<<1|1];    //左儿子的右连续加上右儿子的左连续
            //return len[st<<1|1];
            else  //x在右儿子的右连续区间
            return query(x,rson);
        }
    }
    
    int main() 
    {
        int n,m;
        char ope[5];
        int x;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            build(1,n,1);
            stack<int> destroy;
            while(m--)
            {
                scanf("%s",ope);
                if(ope[0]=='D')
                {
                    scanf("%d",&x);
                    UpdataDes(x,1,n,1);
                    destroy.push(x);
                }
                else if(ope[0]=='R')
                {
                    if(destroy.empty()) continue;
                    x=destroy.top();
                    UpdataRec(x,1,n,1);
                    destroy.pop();
                }
                else
                {
                    scanf("%d",&x);
                    printf("%d
    ",query(x,1,n,1));
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    套接字I/O函数write/read writev/readv send/recv sendto/recvfrom sendmsg/recvmsg
    套接字之recvmsg系统调用
    套接字之recv系统调用
    套接字之recvfrom系统调用
    套接字之sendmsg系统调用
    套接字之send系统调用
    数据类型
    简单的c程序分析
    c语言函数分析
    堆栈图
  • 原文地址:https://www.cnblogs.com/chilkings/p/11946244.html
Copyright © 2011-2022 走看看