zoukankan      html  css  js  c++  java
  • bzoj 3685

    线段树

    方法一:

    值域线段树,递归去写的,每次节点存出现次数.

    对于几个操作, 1,2 直接加减就好 ; 3,4 操作贪心往某一个方向找 .7也很简单,主要说前驱后继怎么找。我是先找这个数第几小,根据相应关系得出我们需要输出第几小。然后就写了一下 TLE。详见代码一;

    解决办法

    加入输入外挂 .... 过了.详见代码二。

    方法二:

    参考了zkw,原来就是递归改为循环,再用到满二叉树性质.有些能够O(1) 求出.

    具体做法:先确定范围,让二叉树最后一层节点数>=n.并找到最后一层节点编号 L-R .和前面有sz个节点. 增删我们从 sz+x这个节点开始加上一个数,之后除以2.
    再写一个查询最大最小.那个函数传入的是节点编号.所以他可以查询某个子树的max,min.结合到前驱后继。比如查询x前驱,我就从x那个最底层点开始,看我是右儿子?如果是,看左儿子节点有数?有查询那颗子树的max,即为答案,反之也是一样的。最后一个操作直接来。sz+x。对于下标处理原题 [0,n-1] . 线段树 是1开始所以减一莫要忘记.
    具体写法,参考代码三。

    //代码一
    #include <stdio.h>
    
    
    
    const int maxn=1e6+10;
    
    
    int T[maxn*4];
    void ins(int i,int l,int r,int x,int val)// 1 2
    {
        if(l==r) 
        {
            T[i]=val;
            return ;
        }
        int mid=(l+r)>>1;
        if(x<=mid) ins(i<<1,l,mid,x,val);
        else ins(i<<1|1,mid+1,r,x,val);
        T[i]=T[i<<1]+T[i<<1|1];
    }
    int fmax(int i,int l,int r)
    {
        if(T[i]==0) return -1;
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(T[i<<1|1]) return fmax(i<<1|1,mid+1,r);
        else return fmax(i<<1,l,mid);
    }
    int fmin(int i,int l,int r)
    {
        if(T[i]==0) return -1;
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(T[i<<1]) return fmin(i<<1,l,mid);
        else return fmin(i<<1|1,mid+1,r);
    }
    
    
    int fx(int i,int l,int r,int x)
    {
        if(l==r) return T[i]?1:-1;
        int mid=(l+r)>>1;
        if(x<=mid) return fx(i<<1,l,mid,x);
        else return fx(i<<1|1,mid+1,r,x);
    }
    
    
    
    bool flag;
    int kth(int i,int l,int r,int x)
    {
        if(l==r) 
        {
            flag=T[i];
            return T[i];
        }
        int mid=(l+r)>>1;
        if(x<=mid) return kth(i<<1,l,mid,x);
        else return T[i<<1]+kth(i<<1|1,mid+1,r,x); 
    }
    
    int fkth(int i,int l,int r,int k)
    {
        if(l==r) 
        {
            if(T[i]) return l;
            else return -1;
        }
        int mid=(l+r)>>1;
        int sum=T[i<<1];
        if(sum>=k) return fkth(i<<1,l,mid,k);
        else return fkth(i<<1|1,mid+1,r,k-sum);
    }
    
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        while(m--)
        {
            int op,x;
            scanf("%d",&op);
            if(op==3||op==4) ;
            else scanf("%d",&x);
    
    
            if(op==1) ins(1,-1,n+1,x,1);
            else if(op==2) ins(1,-1,n+1,x,0);
            else if(op==3) printf("%d
    ",fmin(1,-1,n+1));
            else if(op==4) printf("%d
    ",fmax(1,-1,n+1));
            else if(op==5)
            {
                int k=kth(1,-1,n+1,x);
                //printf("k=%d flag=%d
    ",k,flag?1:0);
                if(flag) k--;
                printf("%d
    ",fkth(1,-1,n+1,k));
            }
            else if(op==6)
            {
                int k=kth(1,-1,n+1,x);
                k++;
                printf("%d
    ",fkth(1,-1,n+1,k));
            }
            else printf("%d
    ",fx(1,-1,n+1,x));
        }
        return 0;
    }
    
    /*
    
    10 100
    1 2
    1 4
    1 6
    1 8
    1 10
    
    */
    
    
    //代码二
    #include <stdio.h>
    
    
    
    const int maxn=1e6+10;
    inline char nc()
    {
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int sc()
    {
        char ch=nc();
        int sum=0;
        while(!(ch>='0'&&ch<='9'))ch=nc();
        while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
        return sum;
    }
    
    int T[maxn*4];
    void ins(int i,int l,int r,int x,int val)// 1 2
    {
        if(l==r) 
        {
            T[i]=val;
            return ;
        }
        int mid=(l+r)>>1;
        if(x<=mid) ins(i<<1,l,mid,x,val);
        else ins(i<<1|1,mid+1,r,x,val);
        T[i]=T[i<<1]+T[i<<1|1];
    }
    int fmax(int i,int l,int r)
    {
        if(T[i]==0) return -1;
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(T[i<<1|1]) return fmax(i<<1|1,mid+1,r);
        else return fmax(i<<1,l,mid);
    }
    int fmin(int i,int l,int r)
    {
        if(T[i]==0) return -1;
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(T[i<<1]) return fmin(i<<1,l,mid);
        else return fmin(i<<1|1,mid+1,r);
    }
    
    
    int fx(int i,int l,int r,int x)
    {
        if(l==r) return T[i]?1:-1;
        int mid=(l+r)>>1;
        if(x<=mid) return fx(i<<1,l,mid,x);
        else return fx(i<<1|1,mid+1,r,x);
    }
    
    
    
    bool flag;
    int kth(int i,int l,int r,int x)
    {
        if(l==r) 
        {
            flag=T[i];
            return T[i];
        }
        int mid=(l+r)>>1;
        if(x<=mid) return kth(i<<1,l,mid,x);
        else return T[i<<1]+kth(i<<1|1,mid+1,r,x); 
    }
    
    int fkth(int i,int l,int r,int k)
    {
        if(l==r) 
        {
            if(T[i]) return l;
            else return -1;
        }
        int mid=(l+r)>>1;
        int sum=T[i<<1];
        if(sum>=k) return fkth(i<<1,l,mid,k);
        else return fkth(i<<1|1,mid+1,r,k-sum);
    }
    
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        while(m--)
        {
            int op,x;
            op=sc();
            if(op==3||op==4) ;
            else x=sc();
    
    
            if(op==1) ins(1,-1,n+1,x,1);
            else if(op==2) ins(1,-1,n+1,x,0);
            else if(op==3) printf("%d
    ",fmin(1,-1,n+1));
            else if(op==4) printf("%d
    ",fmax(1,-1,n+1));
            else if(op==5)
            {
                int k=kth(1,-1,n+1,x);
                //printf("k=%d flag=%d
    ",k,flag?1:0);
                if(flag) k--;
                printf("%d
    ",fkth(1,-1,n+1,k));
            }
            else if(op==6)
            {
                int k=kth(1,-1,n+1,x);
                k++;
                printf("%d
    ",fkth(1,-1,n+1,k));
            }
            else printf("%d
    ",fx(1,-1,n+1,x));
        }
        return 0;
    }
    
    /*
    
    10 100
    1 2
    1 4
    1 6
    1 8
    1 10
    
    */
    
    //代码三
    #include <stdio.h>
    #include <stdlib.h>
    #include <algorithm>
    const int maxn=1e6+10;
    int T[maxn*4],sz,L,R;
    void ins(int i,int val)
    {
        i=i+sz;
        if(T[i]==1&&val==1) return ;
        if(T[i]==0&&val==-1) return ;
        for(;i>0;i>>=1) T[i]+=val;
    }
    int fmax(int i)
    {
        if(T[i]==0) return 0;
        while(i<=sz)
        {
            if(T[i<<1|1]) i=i<<1|1;
            else i=i<<1;
        }
        return i-sz;
    }
    int fmin(int i)
    {
        if(T[i]==0) return 0;
        while(i<=sz)
        {
            if(T[i<<1]) i=i<<1;
            else i=i<<1|1;
        }
        return i-sz;
    }
    int fpre(int i)
    {
        i=i+sz;
        for(;i!=1;i>>=1)
            if((i&1)&&T[i^1]) return fmax(i^1);
        return 0;
    }
    int fsuc(int i)
    {
        i=i+sz;
        for(;i!=1;i>>=1)
            if(!(i&1)&&T[i^1]) return fmin(i^1);
        return 0;
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        sz=0;
        for(int i=1;i<n;i=(i<<1))
        {
            sz+=i;
            L=sz+1;
            R=sz+(i<<1);
        }
        while(m--)
        {
            int op,x;
            scanf("%d",&op);
            if(op==3||op==4);
            else scanf("%d",&x);
            x++;
            if(op==1) ins(x,1);
            else if(op==2) ins(x,-1);
            else if(op==3) printf("%d
    ",fmin(1)-1);
            else if(op==4) printf("%d
    ",fmax(1)-1);
            else if(op==5) printf("%d
    ",fpre(x)-1);
            else if(op==6) printf("%d
    ",fsuc(x)-1);
            else printf("%d
    ",T[sz+x]?1:-1);
        }
        return 0;
    }
    
  • 相关阅读:
    Windows 7 下安装 docker 应用容器引擎
    jmeter压力测试
    1分钟为Win10瘦身!把吃掉的硬盘找回来
    关于IIS应用程序池的默认参数设置解决
    IIS将应用程序池配置为在计划时间执行回收 (IIS 7)
    什么是IIS应用程序池
    WinCE知识介绍
    odoo12 通过一个字段控制另一个Many2one字段的domain
    odoo12 数据库过期问题
    odoo12
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7522087.html
Copyright © 2011-2022 走看看