3196: Tyvj 1730 二逼平衡树

来源:互联网 发布:假身份证淘宝怎么搜 编辑:程序博客网 时间:2024/05/18 02:15
/**************************************************************    Problem: 3196    User: moonbeam    Language: C++    Result: Accepted    Time:5236 ms    Memory:27600 kb****************************************************************/ #include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;#define nn 50010#define inf 0x7fffffffclass multi_treap//multi_treap和treap类似,也是一种排序二叉树,但支持重复元素,其他功能上和treap一样{private:    struct node//multi_treap的节点定义    {        node* ch[2];        int v, r, s, num;        int cmp(int x)        {            if (x == v) return -1;            return(x < v ? 0 : 1);        }    };    node *root;//multi_treap的根    void updata(node* o)    {        if (!o) return;        o->s = o->num;        if (o->ch[0]) o->s += o->ch[0]->s;        if (o->ch[1]) o->s += o->ch[1]->s;    }    void rateto(node* &o, int d)    {        node* k;        k = o->ch[d ^ 1];        o->ch[d ^ 1] = k->ch[d];        k->ch[d] = o;        updata(o);        updata(k);        o = k;    }    void add(node* &o, int x)    {        if (!o)        {            o = new node();            o->ch[0] = o->ch[1] = 0;            o->v = x;            o->r = rand()*rand();            o->s = 1;            o->num = 1;            return;        }        int d = o->cmp(x);        if (d == -1)        {            o->num++;//multi的开关,注释掉可以关闭multi功能            o->s++;        }        else        {            add(o->ch[d], x);            updata(o);            if (o->r < o->ch[d]->r) rateto(o, d ^ 1);        }    }    void remove(node* &o, int x)    {        int d = o->cmp(x);        if (d == -1)        {            if (o->num>1)            {                o->num--;                o->s--;            }            else            {                if (!(o->ch[0]))                {                    node *p = o;                    o = o->ch[1];                    free(p);                    p = 0;                }                else if (!(o->ch[1]))                {                    node *p = o;                    o = o->ch[0];                    free(p);                    p = 0;                }                else                {                    int d2 = o->ch[0]->r > o->ch[1]->r ? 1 : 0;                    rateto(o, d2);                    remove(o->ch[d2], x);                }            }        }        else remove(o->ch[d], x);        updata(o);    }    int left(node* o)    {        if (o->ch[0]) return o->ch[0]->s;        else return 0;    }    int Kth(int k)    {        node *p = root;        while (1)        {            int su = (p->ch[0] ? p->ch[0]->s : 0);            if (su + 1 <= k&&k <= su + p->num) return p->v;            else if (k <= su) p = p->ch[0];            else            {                k -= su + p->num;                p = p->ch[1];            }        }    }    int Rank(int x)    {        int ans = 0;        node *p = root;        while (p)        {            if (p->v == x)            {                ans += 1 + (p->ch[0] ? p->ch[0]->s : 0);                return ans;            }            else            if (x < p->v) p = p->ch[0];            else            {                ans += p->num + (p->ch[0] ? p->ch[0]->s : 0);                p = p->ch[1];            }        }        return ans+1;    }    int RankPlus(int x)    {        int ans = 0;        node *p = root;        while (p)        {            if (p->v == x)            {                ans += p->num + (p->ch[0] ? p->ch[0]->s : 0);                return ans;            }            else            if (x < p->v) p = p->ch[0];            else            {                ans += p->num + (p->ch[0] ? p->ch[0]->s : 0);                p = p->ch[1];            }        }        return ans;    }    int Suc(int x)    {        node* p = root;        int ans = 0;        bool find = 0;        while (p)        {            if (p->v > x)            {                ans = p->v;                find = 1;            }            p = p->ch[p->v <= x];        }        if (find) return ans;        else return -1;    }    int Pre(int x)    {        node *p = root;        int ans = 0;        bool find = 0;        while (p)        {            if (p->v < x)            {                ans = p->v;                find = 1;            }            p = p->ch[p->v < x];        }        if (find) return ans;        else return -1;    }    bool Find(node* o, int x)    {        while (o)        {            int d = o->cmp(x);            if (d == -1) return 1;            else o = o->ch[d];        }        return 0;    }    void mymemory(node* &o)    {        if (!o) return;        if (o->ch[0]) mymemory(o->ch[0]);        if (o->ch[1]) mymemory(o->ch[1]);        free(o);        o = 0;    }    //以上是multi_treap的实现部分public:    int size() //返回multi_treap中元素的个数    {        if (root) return root->s;        else return 0;    }    void insert(int x)//在multi_treap中插入一个x    {        add(root, x);    }    void erase(int x)//删除multi_treap中的元素x,如果multi_treap中x的有多个,则只删除一个    {        remove(root, x);    }    int kth(int x) //返回multi_treap中排名为x的元素的值,如果x非法,则返回-1    {        if (x <= 0 || x > size()) return -1;        else return Kth(x);    }    int rank(int x) //返回x在multi_treap中的排名,如果x没有在multi_treap中,则返回-1    {        return Rank(x);    }    int suc(int x) //返回multi_treap中大于x的第一个元素的值(后驱),如果x大于等于multi_treap中的最大值,则返回-1    {        return Suc(x);    }    int pre(int x) //返回multi_treap中小于x的第一个元素的值(前驱),如果x小于等于multi_treap中的最小值,则返回-1    {        return Pre(x);    }    bool find(int x) //返回x是否在该multi_treap    {        return Find(root, x);    }    void clear() //清空multi_treap    {        mymemory(root);    }    multi_treap() //multi_treap初始化    {        root = 0;    }    int rankplus(int x)    {        return RankPlus(x);    }}treap[nn<<1];int val[nn],use[nn];int cnt;void build(int l,int r){    int id=l+r|l!=r;    for(int i=l;i<=r;i++)        treap[id].insert(val[i]);    if(l==r) return;    int mid=(l+r)>>1;    build(l,mid);    build(mid+1,r);}void choose(int l,int r,int ll,int rr){    int id=l+r|l!=r;    if(ll<=l && r<=rr){        use[cnt++]=id;        return;    }    int mid=(l+r)>>1;    if(ll<=mid)        choose(l,mid,ll,rr);    if(rr>mid)        choose(mid+1,r,ll,rr);}void change(int l,int r,int rt,int v){    int id=l+r|l!=r;    treap[id].erase(val[rt]);    treap[id].insert(v);    if(l==r)  return;    int mid=(l+r)>>1;    if(rt<=mid) change(l,mid,rt,v);    else change(mid+1,r,rt,v);}int main(){    int n,m;    for(int i=0;i<(nn<<1);i++)        treap[i].clear();    while(~scanf("%d%d",&n,&m))    {        for(int i=1;i<=n;i++)            scanf("%d",&val[i]);        build(1,n);        while(m--)        {            int opt;            scanf("%d",&opt);            if(opt==3)            {                int pos,k;                scanf("%d%d",&pos,&k);                change(1,n,pos,k);                val[pos]=k;                continue;            }            int l,r,k;            scanf("%d%d%d",&l,&r,&k);            cnt=0;            choose(1,n,l,r);            //printf("cnt==%d\n",cnt);//            for(int i=0;i<cnt;i++)//                printf("%d ",use[i]);//            printf("\n");            if(opt==1)            {                int ans=0;                for(int i=0;i<cnt;i++)                    ans+=treap[use[i]].rank(k)-1;                printf("%d\n",ans+1);            }            else if(opt==2)            {                int ll=-1,rr=1e8+10;                while(ll<rr)                {                    int mid=(ll+rr)>>1;                    int ans=0;                    for(int i=0;i<cnt;i++)                        ans+=treap[use[i]].rank(mid)-1;                    if(ans+1<=k) ll=mid+1;                    else rr=mid;                }                printf("%d\n",rr-1);            }            else if(opt==4)            {                int ans=-inf;                for(int i=0;i<cnt;i++)                {                    int tmp=treap[use[i]].pre(k);                    if(tmp!=-1)                        ans=max(ans,tmp);                }                printf("%d\n",ans);            }            else if(opt==5)            {                int ans=inf;                for(int i=0;i<cnt;i++)                {                    int tmp=treap[use[i]].suc(k);                    if(tmp!=-1)                        ans=min(ans,tmp);                }                printf("%d\n",ans);            }        }        for(int i=0;i<(nn<<1);i++)            treap[i].clear();    }    return 0;}

0 0
原创粉丝点击