poj3580:SuperMemo

题目大意:维护一个数列,6种操作。

add:给某个区间的数都加一个数

insert:在某数后插一个数

delete:删除某一个数

min:查询区间内最小值

reverse:把某一区间的数反转

revolve:某一区间的数循环向后挪d位

 

题解:

真是标准的splay模板啊。

说起来一年前学的splay现在才能真正写对,好是惭愧……QWQ

add,insert,delete,min都是通过旋转找到指定的区间或位置进行操作,除了min以外其他三个操作完都需update(尤其是add也要,不要忘了!)

reverse需要一个lazy(值为0或1),记录这段区间是否要反转。每次pushdown时只需交换改点左右子,然后把左右子lazy^1就可以了

revolve就先把这一整段区间reverse,然后把这时的前d位与后面的分别reverse

 

注意:

由于不断会加数,空间应该开够避免re

为了方便起见前后各加一个点,所以操作前要对输入的区间进行相应的处理

求min的时候不要忘了+lazynum!

#include <cstdio>
#include <iostream>
#define INF 10000000
using namespace std;

const int MAXN=100005;
struct node
{
    int d,Min,size,lazy,lazynum;
    node *parent,*ch[2];
}pool[MAXN*4],*root,*rf;
int cnt,n;

int size(node *p)
{
    if(p) return p->size;
    return 0;
}

void update(node *p)
{
    p->size=1+size(p->ch[0])+size(p->ch[1]);
    p->Min=p->d;
    if(p->ch[0]) p->Min=min(p->Min,p->ch[0]->Min+p->ch[0]->lazynum);
    if(p->ch[1]) p->Min=min(p->Min,p->ch[1]->Min+p->ch[1]->lazynum);
}

void pushdown(node *p)
{
    if(p->lazy)
    {
        swap(p->ch[0],p->ch[1]);
        if(p->ch[0]) p->ch[0]->lazy^=1;
        if(p->ch[1]) p->ch[1]->lazy^=1;
        p->lazy=0;
    }
    if(p->lazynum)
    {
        p->d+=p->lazynum;
        p->Min+=p->lazynum;
        if(p->ch[0]) p->ch[0]->lazynum+=p->lazynum;
        if(p->ch[1]) p->ch[1]->lazynum+=p->lazynum;
        p->lazynum=0;
    }
}

void rotate(node *p,int type)//left:0  right:1
{
    node *parent=p->parent,*son=p->ch[!type],*gp=p->parent->parent;
    parent->ch[type]=son;
    if(son) son->parent=parent;
    p->ch[!type]=parent;
    parent->parent=p;
    p->parent=gp;
    gp->ch[parent==gp->ch[1]]=p;
    if(parent==root) root=p;
    update(parent);
    update(p);
}

void splay(node *p,node *target)
{
    while(p->parent!=target)
    {
        if(p->parent->parent==target)
            rotate(p,p==p->parent->ch[1]);
        else
        {
            node *parent=p->parent,*gp=p->parent->parent;
            int f=parent==gp->ch[0];
            if(p==parent->ch[f]) rotate(p,f),rotate(p,!f);
            else rotate(parent,!f),rotate(p,!f);
        }
    }
}

node *find(node *p,int k)
{
    pushdown(p);
    if(size(p->ch[0])>=k) return find(p->ch[0],k);
    else if(size(p->ch[0])==k-1) return p;
    else return find(p->ch[1],k-1-size(p->ch[0]));
}

void insert(int x,int d)
{
    node *newnode=&pool[++cnt];
    newnode->size=1;newnode->d=newnode->Min=d;newnode->lazy=newnode->lazynum=0;
    node *p=find(root,x);
    splay(p,rf);
    p=find(root,x+1);
    splay(p,root);
    p->ch[0]=newnode;
    newnode->parent=p;
    update(p);update(p->parent);
}

void del(int x)
{
    node *p=find(root,x-1);
    splay(p,rf);
    p=find(root,x+1);
    splay(p,root);
    p->ch[0]=NULL;
    update(p);update(p->parent);
}

void add(int x,int y,int d)
{
    if(x>y) swap(x,y);
    node *p=find(root,x-1);
    splay(p,rf);
    p=find(root,y+1);
    splay(p,root);
    p->ch[0]->lazynum+=d;
    update(p);update(p->parent);
}

int GetMin(int x,int y)
{
    if(x>y) swap(x,y);
    node *p=find(root,x-1);
    splay(p,rf);
    p=find(root,y+1);
    splay(p,root);
    return p->ch[0]->Min+p->ch[0]->lazynum;
}

void reverse(int x,int y)
{
    if(x>y) swap(x,y);
    node *p=find(root,x-1);
    splay(p,rf);
    p=find(root,y+1);
    splay(p,root);
    p->ch[0]->lazy^=1;
}

void revolve(int x,int y,int d)
{
    if(x>y) swap(x,y);
    d=d%(y-x+1);
    if(d==0) return;
    reverse(x,y);
    reverse(x,x+d-1);
    reverse(x+d,y);
}

void inorder(node *p)
{
    pushdown(p);
    if(p->ch[0]) inorder(p->ch[0]);
    printf("%d ",p->d);
    if(p->ch[1]) inorder(p->ch[1]);
}

int main()
{
    scanf("%d",&n);
    int m,i,a,x,y;
    char ch[8];
    rf=&pool[++cnt];
    root=&pool[++cnt];
    root->d=root->Min=INF;root->size=1;
    root->lazy=root->lazynum=0;
    root->parent=rf;rf->ch[0]=root;
    
    node *p;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a);
        p=&pool[++cnt];
        p->d=p->Min=a;p->size=1;
        p->lazy=p->lazynum=0;
        p->parent=root;
        root->ch[1]=p;
        splay(p,rf);
    }
    p=&pool[++cnt];
    p->d=p->Min=INF;p->size=1;
    p->lazy=p->lazynum=0;
    p->parent=root;
    root->ch[1]=p;
    splay(p,rf);
   
    scanf("%d",&m);
    while(m --> 0)
    {
        cin>>ch;
        if(ch[0]=='A')
        {
            scanf("%d%d%d",&x,&y,&a);
            x++,y++;
            add(x,y,a);
        }
        else if(ch[0]=='D')
        {
            scanf("%d",&x);
            x++;
            del(x);
        }
        else if(ch[0]=='I')
        {
            scanf("%d%d",&x,&y);
            x++;
            insert(x,y);
        }
        else if(ch[0]=='M')
        {
            scanf("%d%d",&x,&y);
            x++,y++;
            printf("%d\n",GetMin(x,y));
        }
        else if(ch[3]=='E')
        {
            scanf("%d%d",&x,&y);
            x++,y++;
            reverse(x,y);
        }
        else
        {
            scanf("%d%d%d",&x,&y,&a);
            x++,y++;
            revolve(x,y,a);
        }
    }
    return 0;
}

 

posted @ 2017-06-06 16:14  秋千旁的蜂蝶~  阅读(223)  评论(0编辑  收藏  举报