SuperMemo POJ - 3580

http://poj.org/problem?id=3580

伸展树的各种操作 收口袋大法好 一开始看模板上额外在维护数列的二叉树上又加了两个节点 root和root->ch[1] 觉得很蒙逼 但是这样保证了每次取前驱后继时不会越界 这两个节点的角色就相当于数组中的啊a[0]和a[n+1]

题目很坑逼 数据范围不给 循环次数可能是负数

还要注意longlong不能用max/min 必须手写

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define N 0x3f3f3f3f3f3f3f3f

ll getmin(ll a,ll b);
struct node;
node *null;

struct node
{
    node *fa,*ch[2];
    int sz,rev;
    ll val,minn,laz;
    void wipe()
    {
        fa=ch[0]=ch[1]=null;
        sz=1,val=0,minn=N,laz=0,rev=0;
    }
    int getd()
    {
        return fa->ch[1]==this;
    }
    void setc(node *tmp,int d)
    {
        ch[d]=tmp;
        tmp->fa=this;
    }
    void add(ll tlaz)
    {
        if(this==null) return;
        val+=tlaz,minn+=tlaz,laz+=tlaz;
    }
    void reverse()
    {
        if(this==null) return;
        swap(ch[0],ch[1]);
        rev^=1;
    }
    void pushup()
    {
        sz=ch[0]->sz+ch[1]->sz+1;
        minn=N;
        if(ch[0]!=null) minn=min(minn,min(ch[0]->val,ch[0]->minn));
        if(ch[1]!=null) minn=min(minn,min(ch[1]->val,ch[1]->minn));
    }
    void pushdown()
    {
        if(laz!=0)
        {
            ch[0]->add(laz);
            ch[1]->add(laz);
            laz=0;
        }
        if(rev!=0)
        {
            ch[0]->reverse();
            ch[1]->reverse();
            rev=0;
        }
    }
};

node pool[200010];
node *root,*tail;
ll ary[100010];
int n,q;

void build(node *&cur,node *fa,int l,int r)
{
    int m;
    if(l>r) return;
    m=(l+r)/2;
    cur=tail++;
    cur->wipe();
    cur->fa=fa;
    cur->val=ary[m],cur->minn=N,cur->laz=0,cur->rev=0;
    build(cur->ch[0],cur,l,m-1);
    build(cur->ch[1],cur,m+1,r);
    cur->pushup();
}

void init()
{
    node *tmp;
    tail=pool;
    null=tail++;
    null->fa=null->ch[0]=null->ch[1]=null;
    null->sz=0,null->val=0,null->minn=N,null->laz=0,null->rev=0;
    tmp=tail++;
    tmp->wipe();
    root=tmp;
    tmp=tail++;
    tmp->wipe();
    root->setc(tmp,1);
    build(root->ch[1]->ch[0],root->ch[1],1,n);
    root->ch[1]->pushup();
    root->pushup();
}

node *getkth(node *r,int k)
{
    node *cur;
    cur=r;
    cur->pushdown();
    while(cur->ch[0]->sz+1!=k)
    {
        if(cur->ch[0]->sz+1>k)
        {
            cur=cur->ch[0];
        }
        else
        {
            k-=(cur->ch[0]->sz+1);
            cur=cur->ch[1];
        }
        cur->pushdown();
    }
    return cur;
}

void rotate(node *cur)
{
    node *f,*ff;
    int c,cc;
    f=cur->fa,ff=cur->fa->fa;
    f->pushdown();
    cur->pushdown();
    c=cur->getd(),cc=f->getd();
    f->setc(cur->ch[!c],c);
    cur->setc(f,!c);
    if(ff->ch[cc]==f) ff->setc(cur,cc);
    else cur->fa=ff;
    f->pushup();
}

void splay(node *&root,node *tar,node *cur)
{
    while(cur->fa!=tar)
    {
        if(cur->fa->fa==tar) rotate(cur);
        else
        {
            cur->fa->fa->pushdown();
            cur->fa->pushdown();
            cur->pushdown();
            if(cur->getd()==cur->fa->getd()) rotate(cur->fa);
            else rotate(cur);
            rotate(cur);
        }
    }
    cur->pushup();
    if(tar==null) root=cur;
}

void insert(node *&cur,node *fa,ll val)
{
    cur=tail++;
    cur->wipe();
    cur->fa=fa;
    cur->val=val,cur->minn=N,cur->laz=0,cur->rev=0;
}
ll getmin(ll a,ll b)
{
    if(a<b) return a;
    else return b;
}

void show()
{
    node *ptr;
    int i;
    printf("******\n");
    for(i=2;i<=n+1;i++)
    {
        ptr=getkth(root,i);
        printf("%I64d ",ptr->val);
    }
    printf("\n");
    printf("******\n");
}

int main()
{
    ll val,len;
    int i,l,r;
    char op[10];
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%I64d",&ary[i]);
    }
    init();
    scanf("%d",&q);
    while(q--)
    {
        scanf("%s",op);
        if(strcmp(op,"ADD")==0)
        {
            scanf("%d%d%I64d",&l,&r,&val);
            splay(root,null,getkth(root,l));
            splay(root,root,getkth(root,r+2));
            root->ch[1]->ch[0]->add(val);
            root->ch[1]->pushup();
            root->pushup();
        }
        else if(strcmp(op,"REVERSE")==0)
        {
            scanf("%d%d",&l,&r);
            splay(root,null,getkth(root,l));
            splay(root,root,getkth(root,r+2));
            root->ch[1]->ch[0]->reverse();
            root->ch[1]->pushup();
            root->pushup();
        }
        else if(strcmp(op,"REVOLVE")==0)
        {
            scanf("%d%d%I64d",&l,&r,&val);
            //val=max(val,0ll);
            len=r-l+1;
            if(len==1) continue;
            val+=1000000000ll*len;
            if(val%len!=0)
            {
                val%=len;
                //printf("^^^%I64d^^^\n",val);
                splay(root,null,getkth(root,l));
                splay(root,root,getkth(root,r+2));
                root->ch[1]->ch[0]->reverse();
                root->ch[1]->pushup();
                root->pushup();
                if(val>1)
                {
                    splay(root,null,getkth(root,l));
                    splay(root,root,getkth(root,l+val+1));
                    root->ch[1]->ch[0]->reverse();
                    root->ch[1]->pushup();
                    root->pushup();
                }

                if(r-l-val+1>1)
                {
                    splay(root,null,getkth(root,l+val));
                    splay(root,root,getkth(root,r+2));
                    root->ch[1]->ch[0]->reverse();
                    root->ch[1]->pushup();
                    root->pushup();
                }
            }
        }
        else if(strcmp(op,"INSERT")==0)
        {
            scanf("%d%I64d",&l,&val);
            splay(root,null,getkth(root,l+1));
            splay(root,root,getkth(root,l+2));
            insert(root->ch[1]->ch[0],root->ch[1],val);
            root->ch[1]->pushup();
            root->pushup();
        }
        else if(strcmp(op,"DELETE")==0)
        {
            scanf("%d",&l);
            splay(root,null,getkth(root,l));
            splay(root,root,getkth(root,l+2));
            root->ch[1]->ch[0]=null;
            root->ch[1]->pushup();
            root->pushup();
        }
        else
        {
            scanf("%d%d",&l,&r);
            splay(root,null,getkth(root,l));
            splay(root,root,getkth(root,r+2));
            printf("%I64d\n",getmin(root->ch[1]->ch[0]->val,root->ch[1]->ch[0]->minn));
            //printf("$$$%lld %lld$$$\n",root->ch[1]->ch[0]->val,root->ch[1]->ch[0]->minn);
        }
        //show();
    }
    return 0;
}

/*
10
1 4 7 8 9 6 3 2 5 10
10
REVERSE 3 8
REVOLVE 5 10 -2147483647
DELETE 1
INSERT 0 5
INSERT 10 4
REVOLVE 1 11 -1111111111
REVOLVE 1 11 5
ADD 8 11 2
MIN 1 6
MIN 8 11

10
1 2 3 4 5 6 7 8 9 10
15
ADD 4 8 3
MIN 5 7
MIN 7 10
REVERSE 2 5
MIN 2 6
MIN 2 3
INSERT 3 4
MIN 3 4
MIN 5 10
DELETE 6
MIN 3 5
MIN 4 4
REVOLVE 3 6 7
MIN 5 8
MIN 7 10
*/

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/81782843
POJ