bzoj3196 [TYVJ1730]二逼平衡树 树套树 线段树套ScapeGoat_Tree

人傻自带大常数

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 1500005
using namespace std;
const double A=0.756;
const int inf=100000000;
int n,m,a[50005];
struct ScapeGoat_Tree
{
    ScapeGoat_Tree *ch[2];
    int ex,cover,size,key;
    bool bad()
    {
        return cover*A<ch[0]->cover||cover*A<ch[1]->cover;
    }
    void pushup()
    {
        size=ch[0]->size+ch[1]->size+ex;
        cover=ch[0]->cover+ch[1]->cover+1;
    }
}*null,pool[MAXN],*stack[MAXN],*lst[MAXN];
int top,len;
inline void Init()
{
   null=pool;
   null->cover=null->size=null->ex=null->key=0;
   null->ch[1]=null->ch[0]=null;
   for(int i=1;i<MAXN;i++)stack[++top]=pool+i;
}
inline ScapeGoat_Tree *New(int key)
{
   ScapeGoat_Tree *p=stack[top--];
   p->ch[1]=p->ch[0]=null;
   p->ex=p->cover=p->size=1;
   p->key=key;
   return p;
}
struct Tree
{
    Tree *ch[2];
    int l,r,mid;
    ScapeGoat_Tree *root;
    Tree(){ch[1]=ch[0]=NULL;root=null;}
    void* operator new(size_t size);
}*root,*C,*mempool;
void* Tree :: operator new(size_t size)
{
    if(C==mempool)
    {
       C=new Tree[(1<<15)+10];
       mempool=C+(1<<15)+10;
    }
    return C++;
}
void travel(ScapeGoat_Tree *p)
{
    if(p==null)return;
    travel(p->ch[0]);
    if(p->ex) lst[++len]=p;
    else stack[++top]=p;
    travel(p->ch[1]);
}
ScapeGoat_Tree *divide(int l,int r)
{
    if(l>r)return null;
    int mid=(l+r)>>1;
    lst[mid]->ch[0]=divide(l,mid-1);
    lst[mid]->ch[1]=divide(mid+1,r);
    lst[mid]->pushup();
    return lst[mid];
}
ScapeGoat_Tree **insert(ScapeGoat_Tree *&p,int key)
{
    if(p==null)
    {
       p=New(key);
       return &null;
    }
    p->size++;
    p->cover++;
    ScapeGoat_Tree **ret=insert(p->ch[p->key<=key],key);
    if(p->bad())ret=&p;
    return ret;
}
inline void rebuild(ScapeGoat_Tree *&p)
{
    len=0;
    travel(p);
    p=divide(1,len);
}
inline void Insert(ScapeGoat_Tree *&Root,int key)
{
    ScapeGoat_Tree **p=insert(Root,key);
    if(*p!=null)rebuild(*p);
}
inline int rank(ScapeGoat_Tree *p,int key)
{
    int ret=0;
    while(p!=null)
     if(p->key>=key)
      p=p->ch[0];
     else
      ret+=p->ch[0]->size+p->ex,p=p->ch[1];
    return ret;
}
void erase(ScapeGoat_Tree *p,int k)
{
    p->size--;
    if(p->ex&&k==p->ch[0]->size+1)
    {
        p->ex=0;
        return;
    }
    if(p->ch[0]->size>=k)
     erase(p->ch[0],k);
    else erase(p->ch[1],k-p->ch[0]->size-p->ex);
}
inline void Erase_kth(ScapeGoat_Tree *&p,int k)
{
    erase(p,k);
    if(p->size<p->cover*A)rebuild(p);
}
inline void Erase(ScapeGoat_Tree *&p,int key)
{
    Erase_kth(p,rank(p,key)+1);
}
void build(Tree *p)
{
    p->mid=(p->l+p->r)>>1;
    if(p->l==p->r)return;
    p->ch[0]=new Tree;
    p->ch[0]->l=p->l;
    p->ch[0]->r=p->mid;
    p->ch[1]=new Tree;
    p->ch[1]->l=p->mid+1;
    p->ch[1]->r=p->r;
    build(p->ch[0]);
    build(p->ch[1]);
}
void get_in(int key,int aim,Tree *p)
{
    Insert(p->root,key);
    if(p->l==p->r)return;
    if(aim<=p->mid)get_in(key,aim,p->ch[0]);
    else get_in(key,aim,p->ch[1]);
}
void get_rank(int l,int r,int key,Tree *p,int &ans)
{

    if(l<=p->l&&p->r<=r)
    {
        ans+=rank(p->root,key);
        return;
    }
    if(l<=p->mid)get_rank(l,r,key,p->ch[0],ans);
    if(p->mid<r)get_rank(l,r,key,p->ch[1],ans);
}
inline int Rank(int l,int r,int key)
{
    int ans=0;
    get_rank(l,r,key,root,ans);
    return ans+1;
}
inline int Kth(int l,int r,int rk)
{
    int z=0,y=inf,mid;
    int ans=0;
    while(z<=y)
    {
       mid=(z+y)>>1;
       int k=Rank(l,r,mid);
       if(k<=rk)
         ans=mid,z=mid+1;
       else
         y=mid-1;
    }
    return ans;
}
void get_out(int aim,int key,Tree *p)
{
    Erase(p->root,key);
    if(p->l==p->r)return;
    if(aim<=p->mid)get_out(aim,key,p->ch[0]);
    else get_out(aim,key,p->ch[1]);
}
inline void work1()
{
    int l,r,k;
    scanf("%d%d%d",&l,&r,&k);
    printf("%d\n",Rank(l,r,k));
}
inline void work2()
{
    int l,r,k;
    scanf("%d%d%d",&l,&r,&k);
    printf("%d\n",Kth(l,r,k));
}
inline void work3()
{
    int aim,key;
    scanf("%d%d",&aim,&key);
    get_out(aim,a[aim],root);
    a[aim]=key;
    get_in(key,aim,root);
}
inline void work4()
{
    int l,r,k;
    scanf("%d%d%d",&l,&r,&k);
    printf("%d\n",Kth(l,r,Rank(l,r,k)-1));
}
inline void work5()
{
    int l,r,k;
    scanf("%d%d%d",&l,&r,&k);
    printf("%d\n",Kth(l,r,Rank(l,r,k+1)));
}
void dfs(Tree *p)
{
    if(p->l==p->r)return;
    dfs(p->ch[0]);
    dfs(p->ch[1]);
}
int main()
{
    freopen("psh.in","r",stdin);
    freopen("psh.out","w",stdout);
    Init();
    root=new Tree;
    root->l=1;
    scanf("%d%d",&n,&m);
    root->r=n;
    build(root);
    dfs(root);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        get_in(a[i],i,root);
    }
    dfs(root);
    int opt;
    while(m--)
    {
        scanf("%d",&opt);
        switch(opt)
        {
            case 1:work1();break;
            case 2:work2();break;
            case 3:work3();break;
            case 4:work4();break;
            case 5:work5();break;
        }
    }
    return 0;
}
时间: 2024-12-23 21:06:35

bzoj3196 [TYVJ1730]二逼平衡树 树套树 线段树套ScapeGoat_Tree的相关文章

BZOJ3196 Tyvj1730 二逼平衡树

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3196 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行有n个数,表示有序

洛谷3380 二逼平衡树(树套树)

题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647) 查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647) 注意上面两条要求和tyvj或者bzoj不一样,请注意 输入输出格式 输入格式: 第一行两个数 n,m 表示长度为n的有序序列和m个操作 第二行有n个数,

二逼平衡树

题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647) 查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647) 注意上面两条要求和tyvj或者bzoj不一样,请注意 输入输出格式 输入格式: 第一行两个数 n,m 表示长度为n的有序序列和m个操作 第二行有n个数,

[Tyvj 1730] 二逼平衡树

先来一发题面QwQ [TYVJ1730]二逼平衡树 Time Limit:2 s   Memory Limit:512 MB Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行有n个数

BZOJ3196二逼平衡树【树套树】

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3776  Solved: 1483 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n

【bzoj3196】 Tyvj 1730 二逼平衡树 线段树套Treap

题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) 输入 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行有n个数,表示有序序列下面有m行,opt表示操作标号若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名若opt=2 则为操

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,

[BZOJ 3196] 二逼平衡树 树状数组套主席树

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3357  Solved: 1326[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为

BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )

这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<ios