hdu1890 Robotic Sort Splay树,区间反转,lazy标记

来源:互联网 发布:怎么让淘宝店铺关掉 编辑:程序博客网 时间:2024/05/29 19:55

对spaly的一些理解:在Splay和Rotate两个操作对树中元素的大小关系是没有影响的,但会影响一些记录如sum值。

这题就以id为key建树,区间反转用rev标记,标记下传时仅交换指向左右儿子的指针,反转后树中元素的大小关系发生了改变。

删除根节点时将右子树中序遍历的第一个点(最小的点)伸展到根节点下,这样右子树的左子树为空。找第一个点时需要pushDown。

#include<iostream>#include<cstring>#include<cstdio>#include<ostream>#include<istream>#include<algorithm>#include<queue>#include<string>#include<cmath>#include<set>#include<map>#include<stack>#include<vector>#define fi first#define se second#define ll long long#define pii pair<int,int>#define inf (1<<30)#define eps 1e-8#define pb push_backusing namespace std;const int maxn=110005;int n;int d[maxn];struct Node{    int w,p;    int id;    bool operator<(const Node& u)const    {        if(w==u.w)            return id<u.id;        return w<u.w;    }}block[maxn];struct SplayTree{    int son[maxn][2],pre[maxn];    int sum[maxn];    int rev[maxn];    int rt,sz;    void init() {        sz=rt=0;        memset(rev,0,sizeof(rev));        son[rt][0]=son[rt][1]=0;        sum[rt]=0;    }    void pushDown(int p)    {        if(rev[p]) {            int ls=son[p][0];            int rs=son[p][1];            rev[ls]=(rev[ls]+1)%2;            rev[rs]=(rev[rs]+1)%2;            son[p][0]=rs;            son[p][1]=ls;            rev[p]=0;        }    }    void Rotate(int x,int c)    {        int y=pre[x];        pushDown(x);        pushDown(y);        son[y][!c]=son[x][c];        pre[son[x][c]]=y;        pre[x]=pre[y];        if(pre[x])            son[pre[y]][son[pre[y]][1]==y]=x;        son[x][c]=y;        pre[y]=x;        pushUp(y);        pushUp(x);    }    void pushUp(int x)    {        sum[x]=sum[son[x][0]]+sum[son[x][1]]+1;    }    void Splay(int x,int goal)    {        pushDown(x);        while(pre[x]!=goal) {            if(pre[pre[x]]==goal) {                pushDown(pre[x]);                pushDown(x);                if(son[pre[x]][0]==x)                    Rotate(x,1);                else                    Rotate(x,0);            }            else {                int y=pre[x],z=pre[y];                pushDown(z); pushDown(y); pushDown(x);                if(son[z][0]==y) {                    if(son[y][0]==x) {                        Rotate(y,1);                        Rotate(x,1);                    }                    else {                        Rotate(x,0);                        Rotate(x,1);                    }                }                else {                    if(son[y][1]==x) {                        Rotate(y,0);                        Rotate(x,0);                    }                    else {                        Rotate(x,1);                        Rotate(x,0);                    }                }            }        }        pushUp(x);        if(goal==0)            rt=x;    }    void newNode(int& rt,int k)    {        rt=++sz;        son[rt][0]=son[rt][1]=0;        block[k].id=k;        block[k].w=d[k];        block[k].p=rt;    }    void build(int& rt,int l,int r,int p)    {        int m=(l+r)/2;        newNode(rt,m);        sum[rt]=r-l+1;        pre[rt]=p;        if(l<=m-1)            build(son[rt][0],l,m-1,rt);        if(m+1<=r)            build(son[rt][1],m+1,r,rt);    }    void Delete()    {        if(son[rt][1]==0 || son[rt][0]==0) {            rt=son[rt][0]+son[rt][1];            pre[rt]=0;        }        else {            int x=son[rt][1];            while(true) {                pushDown(x);                if(son[x][0])                    x=son[x][0];                else                    break;            }            Splay(x,rt);            son[son[rt][1]][0]=son[rt][0];            sum[son[rt][1]]+=sum[son[rt][0]];            pre[son[rt][0]]=son[rt][1];            rt=son[rt][1];            pre[rt]=0;        }    }    void work()    {        for(int i=1;i<=n;i++) {            Splay(block[i].p,0);            if(i==n)                printf("%d\n",i+sum[son[rt][0]]);            else                printf("%d ",i+sum[son[rt][0]]);            rev[son[rt][0]]^=1;            Delete();        }    }} spt;int main(){    while(~scanf("%d",&n)&&n) {        for(int i=1;i<=n;i++)            scanf("%d",&d[i]);        spt.init();        spt.build(spt.rt,1,n,0);        sort(block+1,block+n+1);        spt.work();    }    return 0;}


0 0
原创粉丝点击