tkj
文章143
标签102
分类0
bzoj 3196: Tyvj 1730 二逼平衡树

bzoj 3196: Tyvj 1730 二逼平衡树

.

题意很清楚了吧。。
题解:树套树。我用了个线段树套splay。讲道理可以不用套splay的,但就当练模板了吧。
代码:

#include<bits/stdc++.h>
using namespace std;
struct Splay
{
    struct pnt
    {
        int c,n,sz;
        pnt *f,*s[2];
        pnt(int x,pnt *f):c(x),f(f),n(1),sz(1)
        {
            s[0]=s[1]=0;
        }
    }*root;
    Splay()
    {
        root=0;
    }
    void print(pnt*x)
    {
        if(!x)
        return;
        printf("*%d %d %d ",x->c,x->n,x->sz);
        if(x->s[0])
        printf("l:%d ",x->s[0]->c);
        if(x->s[1])
        printf("r:%d ",x->s[1]->c);
        puts("");
        print(x->s[0]);
        print(x->s[1]);
    }
    void pushup(pnt *x)
    {
        x->sz=x->n;
        if(x->s[0])
        x->sz+=x->s[0]->sz;
        if(x->s[1])
        x->sz+=x->s[1]->sz;
    }
    void rot(pnt *x)
    {
        pnt *f=x->f,*ff=f->f,*R,*r;
        bool w=(x==f->s[0]);
        R=f;r=x->s[w];
        R->s[1-w]=r;
        if(r)
        r->f=R;
        R=ff;r=x;
        if(R)
        R->s[f==ff->s[1]]=r;
        r->f=R;
        R=x;r=f;
        R->s[w]=r;
        r->f=R;
        pushup(f);
        pushup(x);
    }
    void splay(pnt *x,pnt *rt)
    {
        while(x->f!=rt)
        {
            pnt *f=x->f,*ff=f->f;
            if(ff==rt)
            rot(x);
            else if((x==f->s[0])==(f==ff->s[0]))
            {
                rot(f);
                rot(x);
            }
            else
            {
                rot(x);
                rot(x);
            }
        }
        if(!rt)
        root=x;
    }
    void add(int x,pnt *f)
    {
        // printf("f:%d\n",f->c);
        pnt *p=new pnt(x,f);
        if(x<f->c)
        f->s[0]=p;
        else
        f->s[1]=p;
        pushup(f);
        splay(f,0);
    }
    pnt* fd_by_val(int x)
    {
        pnt *now=root;
        while(now->c!=x)
        {
            if(x<now->c)
            {
                if(now->s[0])
                now=now->s[0];
                else
                return now;
            }
            else
            {
                if(now->s[1])
                now=now->s[1];
                else
                return now;
            }
        }
        return now;
    }
    void ins(int x)
    {
        if(!root)
        {
            root=new pnt(x,0);
            return;
        }
        pnt *f=fd_by_val(x);
        // printf("%d\n",f->c);
        if(f->c==x)
        {
            f->n++;
            pushup(f);
            splay(f,0);
        }
        else
        {
            add(x,f);
        }
    }
    int getrank(int x)
    {
        pnt *now=fd_by_val(x);
        splay(now,0);
        // print(root);
        if(now->c>=x)
        {
            if(now->s[0])
            return now->s[0]->sz;
            else
            return 0;
        }
        else
        {
            if(now->s[0])
            return now->s[0]->sz+now->n;
            else
            return now->n;
        }
    }
    int qian(int x)
    {
        pnt *now=fd_by_val(x);
        splay(now,0);/*
        puts("");
        print(root);
        puts("");*/
        if(now->c<x)
        return now->c;
        else
        {
            if(!now->s[0])
            return -1;
            now=now->s[0];
            while(now->s[1])
            now=now->s[1];
            return now->c;
        }
    }
    int hou(int x)
    {
        pnt *now=fd_by_val(x);
        splay(now,0);
        if(now->c>x)
        return now->c;
        else
        {
            if(!now->s[1])
            return 2147483647;
            now=now->s[1];
            while(now->s[0])
            now=now->s[0];
            return now->c;
        }
    }
    void del(int x)
    {
        pnt *hh=fd_by_val(x);/*
        puts("a");
        print(root);
        puts("b");
        printf("%d\n",hh->c);*/
        splay(hh,0);/*
        puts("c");
        print(root);
        puts("d");*/
        if(hh->n>1)
        {
            hh->n--;
            hh->sz--;
        }
        else if(!hh->s[0]&&!hh->s[1])
        {
            root=0;
            delete hh;
        }
        else if(hh->s[0]&&!hh->s[1])
        {
            root=hh->s[0];
            root->f=0;
            delete hh;
        }
        else if(!hh->s[0]&&hh->s[1])
        {
            root=hh->s[1];
            root->f=0;
            delete hh;
        }
        else
        {
            pnt *now=hh->s[0];
            while(now->s[1])
            now=now->s[1];
            splay(now,hh);
            now->s[1]=hh->s[1];
            hh->s[1]->f=now;
            now->f=0;
            root=now;
            pushup(now);
            delete hh;
        }/*
        puts("g");
        print(root);
        puts("f");*/
    }
};
struct tree
{
    int l,r;
    tree *lc,*rc;
    Splay c;
}*rt;
int n,m,a[50010];
tree* bt(int l,int r)
{
    tree *i=new tree;
    i->l=l;
    i->r=r;
    i->lc=i->rc=0;
    if(l<r)
    {
        int md=l+r>>1;
        i->lc=bt(l,md);
        i->rc=bt(md+1,r);
    }
    return i;
}
void add(tree *i,int x,int p)
{
    if(i->l==i->r)
    {
        i->c.ins(x);
        return;
    }
    i->c.ins(x);
    int md=i->l+i->r>>1;
    tree *lc=i->lc,*rc=i->rc;
    if(p<=md)
    add(lc,x,p);
    else
    add(rc,x,p);
}
void chg(tree *i,int x,int p)
{
    if(i->l==i->r)
    {
        i->c.del(a[p]);
        i->c.ins(x);
        return;
    }
    i->c.del(a[p]);
    i->c.ins(x);
    int md=i->l+i->r>>1;
    tree *lc=i->lc,*rc=i->rc;
    if(p<=md)
    chg(lc,x,p);
    else
    chg(rc,x,p);
}
int getrank(tree *i,int l,int r,int x)
{
    if(i->l==l&&i->r==r)
    {/*
        int hh=i->c.getrank(x);
        printf("%d %d %d %d\n",l,r,x,hh);
        return hh;*/
        return i->c.getrank(x);
    }
    int md=i->l+i->r>>1;
    tree *lc=i->lc,*rc=i->rc;
    if(r<=md)
    return getrank(lc,l,r,x);
    else if(l>md)
    return getrank(rc,l,r,x);
    else
    return getrank(lc,l,md,x)+getrank(rc,md+1,r,x);
}
int getkth(int l,int r,int k)
{
    int ll=0,len=100000001;
    while(len)
    {
        int md=ll+(len>>1);
        if(getrank(rt,l,r,md)<k)
        {
            // printf("getrank(%d,%d,%d)=%d\n",l,r,md,getrank(rt,l,r,md));
            ll=md+1;
            len=len-(len>>1)-1;
        }
        else
        len>>=1;
    }
    return ll-1;
}
int getqian(tree *i,int l,int r,int x)
{
    if(i->l==l&&i->r==r)
    {
        // printf("%d %d %d\n",l,r,x);
        return i->c.qian(x);
    }
    int md=i->l+i->r>>1;
    tree *lc=i->lc,*rc=i->rc;
    if(r<=md)
    return getqian(lc,l,r,x);
    else if(l>md)
    return getqian(rc,l,r,x);
    else
    return max(getqian(lc,l,md,x),getqian(rc,md+1,r,x));
}
int gethou(tree *i,int l,int r,int x)
{
    if(i->l==l&&i->r==r)
    {
        return i->c.hou(x);
    }
    int md=i->l+i->r>>1;
    tree *lc=i->lc,*rc=i->rc;
    if(r<=md)
    return gethou(lc,l,r,x);
    else if(l>md)
    return gethou(rc,l,r,x);
    else
    return min(gethou(lc,l,md,x),gethou(rc,md+1,r,x));
}
void print(tree *i,int p)
{
    if(!i)
    return;
    printf("%d %d\n",i->l,i->r);
    i->c.print(i->c.root);
    int md=i->l+i->r>>1;
    if(p<=md)
    print(i->lc,p);
    else
    print(i->rc,p);
}
int main()
{
    scanf("%d%d",&n,&m);
    rt=bt(1,n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        add(rt,a[i],i);
    }/*
    rt->c.print(rt->c.root);
    puts("");*/
    while(m--)
    {
        int op,l,r,k;
        scanf("%d",&op);
        switch(op)
        {
            case 1:
                scanf("%d%d%d",&l,&r,&k);
                printf("%d\n",getrank(rt,l,r,k)+1);
                break;
            case 2:
                scanf("%d%d%d",&l,&r,&k);
                printf("%d\n",getkth(l,r,k));
                break;
            case 3:
                scanf("%d%d",&l,&k);
                chg(rt,k,l);
                a[l]=k;
                break;
            case 4:
                scanf("%d%d%d",&l,&r,&k);
                printf("%d\n",getqian(rt,l,r,k));
                break;
            case 5:
                scanf("%d%d%d",&l,&r,&k);
                printf("%d\n",gethou(rt,l,r,k));
                break;
        }/*
        print(rt,l);
        puts("");
        if(op!=3)
        {
            print(rt,r);
            puts("");
        }*/
    }
}
本文作者:tkj
本文链接:https://tkj666.github.io/50/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可