zoukankan      html  css  js  c++  java
  • P3369 【模板】普通平衡树(权值线段树)

    原来线段树还有这种操作(开成一个桶)

    用区间维护在这个区间内元素的个数,离散化一下,居然能达到splay的效果

    不仅码量大大减少,而且跑的飞快!!!

    6种操作  200多ms

    1. 插入 xx 数
    2. 删除 xx 数(若有多个相同的数,因只删除一个)
    3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 。若有多个相同的数,因输出最小的排名)
    4. 查询排名为 xx 的数
    5. 求 xx 的前驱(前驱定义为小于 xx ,且最大的数)
    6. 求 xx 的后继(后继定义为大于 xx ,且最小的数)
    #include<cstdio>
    #include<iostream>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    #define int long long
    #define ls (o<<1)
    #define rs (ls|1)
    int b[100500];
    int a[100500];
    int val[100500];
    int st[405000];
    int n;
    int tot;
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    inline void put(int x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9)
            put(x/10);
        putchar(x%10+'0');
    }
    inline void add_or_del(int o,int l,int r,int k,int pos)
    {
        st[o]+=pos;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(k<=mid) add_or_del(ls,l,mid,k,pos);
        else add_or_del(rs,mid+1,r,k,pos);
    }
    inline int x_rank_n(int o,int l,int r,int k)
    {
        if(l==r) return 1;
        int mid=(l+r)>>1;
        if(k<=mid) return x_rank_n(ls,l,mid,k);
        else return st[ls]+x_rank_n(rs,mid+1,r,k);
    }
    inline int n_rank_x(int o,int l,int r,int k)
    {
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(st[ls]>=k) return n_rank_x(ls,l,mid,k);
        else return n_rank_x(rs,mid+1,r,k-st[ls]);
    }
    signed main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            val[i]=read();
            a[i]=read();
            if(val[i]!=4)
                b[++tot]=a[i];
        }
        sort(b+1,b+tot+1);
        for(int i=1;i<=n;i++)
        {
            if(val[i]!=4)
                a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
        }
        for(int i=1;i<=n;i++)
        {
            switch(val[i])
            {
                case 1: add_or_del(1,1,tot,a[i],1);break;
                case 2: add_or_del(1,1,tot,a[i],-1);break;
                case 3: put(x_rank_n(1,1,tot,a[i]));putchar('
    ');break;
                case 4: put(b[n_rank_x(1,1,tot,a[i])]);putchar('
    ');break;
                case 5: put(b[n_rank_x(1,1,tot,x_rank_n(1,1,tot,a[i])-1)]);putchar('
    ');break;
                default: put(b[n_rank_x(1,1,tot,x_rank_n(1,1,tot,a[i]+1))]);putchar('
    ');
            }
        }
        return 0;
    }

    so   good。。。

    ----olinr
  • 相关阅读:
    cookie和session学习笔记
    Listener和Filter学习笔记
    [转载]mysql root密码忘了怎么办
    [转载]oracle连不上的各种现象
    Oauth入门学习
    XML学习笔录
    共享内存
    守护进程
    Linux系统调用与文件I/O(一)
    我的第一篇博客
  • 原文地址:https://www.cnblogs.com/olinr/p/9414963.html
Copyright © 2011-2022 走看看