poj3580:SuperMemo(块状链表/Splay)

传送门

  • 题意:

题目要求实现一种数据结构,支持6种操作:
add x,y D:第x个数到第y个数之间的数每个加D;
reverse x y:第x个数到第y个数之间全部数翻转;
revolve x y T:第x个数到第y个数之间的数,向后循环流动T次,即后面T个数变成这段子序列的最前面T个,前面的被挤到后面。
Insert x P:在第x个数后面插入一个数P。
Delete x:删除第x个数。
Min x,y:求第x个数到第y个数之间的最小数字。

  • 题解

1.块状链表。这是很好想而且很好写的,全是暴力操作。感兴趣的可以自己学习学习。(1400ms)

2.Splay。虽然时间复杂度比块状链表优(1087ms,其实也没优什么,主要是Splay常数大),但是代码特别长(块状链表250行,Splay400行)。用Splay主要注意两点,一是打标记(Add,Reverse操作),二是提取区间(即要操作的区间),提取方法很简单,将区间前一位置于rt,将区间后一位置于rt的右儿子,那么对rt右儿子的左儿子操作即可。

主要是Revolve操作有点难写,下面给出做法:

很显然是将[r-c+1,r]的区间提取到[l,r-c]之前,那么先提取前面的区间,再将l-1置为根节点,将l置为l-1的右儿子,将刚才提取的区间置为l左儿子即可。

(注意判断边界以及及时更新。。。)

  • Code1(块状链表):1454MS
#include <algorithm> 
#include <iostream> 
#include <cstring> 
#include <cstdio> 
#include <cmath> 
using namespace std; 

inline int read(); 
const int N = 1e5 + 5, INF = 0x7fffffff, SIZEINT = sizeof(int); 
const int SQRTN = 500, B = 1000, SMIN = SQRTN / 2, SMAX = SQRTN * 2; 
int n, m, a[N]; 

typedef struct Block* PBlock; 
typedef struct List* PList; 
struct Block 
{ 
    int a[SQRTN * 5]; 
    int size, tag, rev, ans; 

    inline void calc() 
    { 
        tag = rev = 0; ans = INF; 
        for (int i = 0; i < size; ++i) 
        if (a[i] < ans) ans = a[i]; 
    } 

    inline void downdate() 
    { 
        if (tag != 0)
        { 
            for (int i = 0; i < size; ++i)a[i] += tag; 
            tag = 0; 
        } 
        if (rev)
        { 
            rev = 0; 
            for (int i = 0; i << 1 < size; ++i)
            { 
                int t = a[i]; 
                a[i] = a[size - i - 1]; 
                a[size - i - 1] = t; 
            } 
        } 
    } 
}used[B]; 

PBlock pool, *top, unused[B]; 
struct List 
{ 
    PBlock a; 
    PList last, next; 
}USED[B]; 

PList head, tail, POOL, *TOP, UNUSED[B]; 

inline PBlock newBlock() 
{ 
    if (top != unused) return *--top; 
    return pool++; 
} 

inline void delBlock(PBlock x) 
{ 
    *top++ = x; 
} 

inline PList newList() 
{ 
    if (TOP != UNUSED) return *--TOP; 
    return POOL++; 
} 

inline void delList(PList x) 
{ 
    *TOP++ = x; 
} 

inline void Build(int *a, const int &n, PList *h, PList *t) 
{ 
    for (int i = 0; i < n; i += SQRTN) 
    { 
        PList p = newList(); 
        p->a = newBlock(); 
        p->a->size = i + SQRTN < n ? SQRTN : n - i; 
        memcpy(p->a->a, a + i, SIZEINT * p->a->size); 
        p->a->calc(); 
        p->last = *t; p->next = NULL; 
        if (*t != NULL) (*t)->next = p; 
        else *h = p; 
        *t = p; 
    } 
} 

inline void merge(PList x) 
{ 
    PList p = x->next; 
    x->a->downdate(); 
    p->a->downdate(); 
    memcpy(x->a->a + x->a->size, p->a->a, SIZEINT * p->a->size); 
    x->a->size += p->a->size; 
    x->a->calc(); 
    x->next = p->next; 
    if (p->next) p->next->last = x; 
    else tail = x; 
    delBlock(p->a); 
    delList(p); 
} 

inline void split(PList x, const int &n) 
{ 
    PList p = newList(); 
    p->a = newBlock(); 
    x->a->downdate(); 
    p->a->size = x->a->size - n; 
    memcpy(p->a->a, x->a->a + n, SIZEINT * p->a->size); 
    x->a->size = n; 
    x->a->calc(); 
    p->a->calc(); 
    p->next = x->next; 
    if (x->next) x->next->last = p; 
    else tail = p; 
    x->next = p; p->last = x; 
} 

inline void Balance() 
{ 
    for (PList p = head; p; p = p->next) 
    { 
        while (p != tail && p->a->size < SMIN)merge(p); 
        if (p->a->size > SMAX)split(p, SQRTN); 
    } 
} 

inline void Delete(PList x) 
{ 
    if (x->last != NULL) x->last->next = x->next; 
    else head = x->next; 
    if (x->next != NULL) x->next->last = x->last; 
    else tail = x->last; 
    delBlock(x->a); 
    delList(x); 
} 

inline PList findl(int n) 
{ 
    PList p = head; 
    for (; n > p->a->size; p = p->next) n -= p->a->size; 
    if (n != 1) 
    { 
        split(p, n - 1); 
        p = p->next; 
    } 
    return p; 
} 

inline PList findr(int n) 
{ 
    PList p = head; 
    for (; n > p->a->size; p = p->next) n -= p->a->size; 
    if (n != p->a->size) split(p, n); 
    return p; 
} 

inline void Init() 
{ 
    pool = used; POOL = USED; 
    top = unused; TOP = UNUSED; 
    head = tail = NULL; 
} 

char ch; 
inline int read() 
{ 
    int res = 0, sgn = 0; 
    while (ch = getchar(), ch < '0' || ch > '9') if (ch == '-') sgn = 1; 
    res = ch - 48; 
    while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48; 

    return sgn ? -res : res; 
} 

int main() 
{ 
    Init(); 
    n = read(); 
    for (int i = 0; i < n; ++i) a[i] = read(); 
    Build(a, n, &head, &tail); 
    m = read(); 
    char type; 
    int l, r, v; 
    PList fr, en, t; 
    PBlock tmp; 
    while (m--) 
    { 
        Balance(); 
        while (type = getchar(), type < 'A' || type > 'Z'); 
        if (type == 'A') 
        { 
            l = read(); r = read(); v = read(); 
            if (l > r) swap(l, r); 
            fr = findl(l); en = findr(r); 
            for (en = en->next; fr != en; fr = fr->next) 
            { 
                fr->a->tag += v; 
                fr->a->ans += v; 
            } 
        } 
        else if (type == 'I') 
        { 
            l = read(); r = read(); 
            fr = findr(l); 
            fr->a->downdate(); 
            fr->a->a[fr->a->size++] = r; 
            if (r < fr->a->ans) fr->a->ans = r; 
        } 
        else if (type == 'D') 
        { 
            l = read(); 
            fr = findl(l); 
            if (fr->a->size != 1) 
            split(fr, 1); 
            Delete(fr); 
        } 
        else if (type == 'M') 
        { 
            l = read(); r = read(); 
            if (l > r) swap(l, r); 
            fr = findl(l); en = findr(r); 
            int ans = INF; 
            for (en = en->next; fr != en; fr = fr->next) 
            if (fr->a->ans < ans) ans = fr->a->ans; 
            printf("%d\n", ans); 
        } 
        else 
        { 
            getchar(); getchar(); type = getchar(); 
            if (type == 'E') 
            { 
                l = read(); r = read(); 
                if (l > r) swap(l, r); 
                fr = findl(l); en = findr(r); 
                while (fr != en && fr != en->next) 
                { 
                    fr->a->rev ^= 1; en->a->rev ^= 1; 
                    tmp = fr->a; 
                    fr->a = en->a; 
                    en->a = tmp; 
                    fr = fr->next; 
                    en = en->last; 
                } 
            if (fr == en) fr->a->rev ^= 1; 
            } 
            else 
            { 
                l = read(); r = read(); 
                if (l > r) swap(l, r); 
                v = read() % (r - l + 1); 
                if (v == 0 || l == r) continue; 
                v = r - l + 1 - v; 
                fr = findl(l); en = findr(r); 
                for (t = fr; v > t->a->size; t = t->next) v -= t->a->size; 
                if (v != t->a->size) 
                { 
                    split(t, v); 
                    if (en == t) en = en->next; 
                } 
                PList p1 = fr->last, p2 = fr, p3 = t, p4 = t->next, p5 = en, 
                p6 = en->next; 
                if (p1 != NULL) 
                { 
                    p1->next = p4; 
                    p4->last = p1; 
                } 
                else head = p4, p4->last = NULL; 
                if (p6 != NULL)
                { 
                    p6->last = p3; 
                    p3->next = p6; 
                } 
                else tail = p3, p3->next = NULL; 
                p5->next = p2; 
                p2->last = p5; 
            } 
        } 
    } 
     return 0; 
} 
  • Code2(Splay):1047ms
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int Maxn=2e5+50;
const int INF=0x3f3f3f3f;
inline int read()
{
    char ch=getchar();int i=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
    return i*f;
}

struct node
{
    node *fa,*lc,*rc;
    int val,taga,tagr,mn,sze;
    node():fa(NULL),lc(NULL),rc(NULL){}
    inline void upt()
    {
        sze=(lc?lc->sze:0)+(rc?rc->sze:0)+1;
        mn=min(val,min(lc?lc->mn:INF,rc?rc->mn:INF));
    }
}POOL[Maxn],*pool=POOL,*rt,*que[Maxn];

int n,m,a[Maxn],bg,ed;
char ch[10];

inline void add(node *now,int val)
{
    now->val+=val;
    now->mn+=val;
    now->taga+=val;
}

inline void addr(node *now)
{
    swap(now->lc,now->rc);
    now->tagr^=1;
}

inline node* newnode(int val)
{
    ++pool;
    pool->val=val;
    pool->mn=val;
    pool->sze=1;
    return pool;
}

inline void build(node *&now,int l,int r)
{
    int mid=(l+r)>>1;
    now=newnode(a[mid]);
    if(l<mid)build(now->lc,l,mid-1);
    if(r>mid)build(now->rc,mid+1,r);
    if(now->lc)now->lc->fa=now;
    if(now->rc)now->rc->fa=now;
    now->upt();
}


inline void pushdown(node *now)
{
    if(now->taga)
    {
        if(now->lc)
        {
            now->lc->mn+=now->taga;
            now->lc->val+=now->taga;
            now->lc->taga+=now->taga;
        }
        if(now->rc)
        {
            now->rc->mn+=now->taga;
            now->rc->val+=now->taga;
            now->rc->taga+=now->taga;
        }
        now->taga=0;
    }
    if(now->tagr)
    {
        if(now->lc)
        {
            swap(now->lc->lc,now->lc->rc);
            now->lc->tagr^=1;
        }
        if(now->rc)
        {
            swap(now->rc->lc,now->rc->rc);
            now->rc->tagr^=1;
        }
        now->tagr^=1;   
    }
}

inline node* find(node *now,int k)
{
    pushdown(now);now->upt();
    if((now->lc?now->lc->sze:0)==k-1)return now;
    else if((now->lc?now->lc->sze:0)>k-1)return find(now->lc,k);
    else return find(now->rc,k-(now->lc?now->lc->sze:0)-1);
}

inline void Rotate(node *x)
{
    node *y=x->fa,*z=y->fa;
    y->fa=x;x->fa=z;
    if(z){((z->lc==y)?(z->lc):(z->rc))=x;}
    if(y->lc==x)
    {
        node* b=x->rc;
        if(b)b->fa=y;
        y->lc=b;
        x->rc=y;
    }
    else
    {
        node* b=x->lc;
        if(b)b->fa=y;
        y->rc=b;
        x->lc=y;
    }
    y->upt();x->upt();
}

inline bool which(node* x)
{
    return x->fa->lc==x;
}

inline void Splay(node* x,node* tar=NULL)
{
    que[ed=1]=x;
    for(node* y=x;y!=rt;y=y->fa)que[++ed]=y->fa;
    for(int i=ed;i>=1;i--){node* y=que[i];pushdown(y);}
    while(x->fa!=tar)
    {
        node* y=x->fa,*z=y->fa;
        if(z!=tar)
        {
            if(which(x)^which(y))Rotate(x);
            else Rotate(y);
        }
        Rotate(x);
    }
    if(!tar)rt=x;
}

inline node* split(int l,int r)
{
    if(l&&r<=n)
    {
        node *t1=find(rt,l);
        node *t2=find(rt,r);
        Splay(t1);Splay(t2,rt);
        node *t3=t2->lc;
        t2->lc=NULL;
        t2->upt();
        t3->fa=NULL;
        return t3;
    }
    else if(!l)
    {
        node *t2=find(rt,r);
        Splay(t2);
        node *t3=t2->lc;
        t2->lc=NULL;
        t2->upt();
        t3->fa=NULL;
        return t3;
    }
    else
    {
        node *t1=find(rt,l);
        Splay(t1);
        node *t3=t1->rc;
        t3->fa=NULL;
        t1->rc=NULL;
        t1->upt();
        return t3;
    }
}

int buf[50];
inline void W(int x)
{
    if(!x){putchar('0');return;}
    if(x<0)putchar('-'),x=-x;
    while(x)buf[++buf[0]]=x%10,x/=10;
    while(buf[0])putchar('0'+buf[buf[0]--]);
    return;
}

int main()
{
    n=read();
    for(int i=1;i<=n;i++){a[i]=read();}
    build(rt,1,n);
    m=read();
    while(m--)
    {
        scanf("%s",ch+1);
        if(ch[1]=='A')
        {
            int l=read(),r=read(),v=read();
            if(l==1&&r==n)add(rt,v);
            else if(l==1)
            {
                node* t2=find(rt,r+1);
                Splay(t2);
                add(rt->lc,v);
                rt->upt();
            }
            else if(r==n)
            {
                node* t1=find(rt,l-1);
                Splay(t1);
                add(rt->rc,v);
                rt->upt();
            }
            else 
            {
                node* t1=find(rt,l-1);
                node* t2=find(rt,r+1);
                Splay(t1);
                Splay(t2,rt);
                add(t2->lc,v);
                t2->upt();t1->upt();
            }
        }
        else if(ch[1]=='I')
        {
            int x=read(),y=read();
            if(x!=0&&x!=n)
            {
                node* t1=find(rt,x);
                node* t2=find(rt,x+1);
                Splay(t1);
                Splay(t2,rt);
                t2->lc=newnode(y);
                t2->lc->fa=t2;
                t2->upt();t1->upt();
                n++;
            }
            else if(x!=0)
            {
                node* t1=find(rt,x);
                Splay(t1);
                t1->rc=newnode(y);
                t1->rc->fa=t1;
                t1->upt();
                n++;
            }
            else
            {
                node* t2=find(rt,x+1);
                t2->lc=newnode(y);
                t2->lc->fa=t2;
                t2->upt();
                n++;
            }       
        }
        else if(ch[1]=='D')
        {
            int pos=read();
            if(pos!=1&&pos!=n)
            {
                node* t1=find(rt,pos-1);
                node* t2=find(rt,pos+1);
                Splay(t1);
                Splay(t2,rt);
                t2->lc->fa=NULL;
                t2->lc=NULL;
                t2->upt();
                rt->upt();
                n--;
            }
            else if(pos!=1)
            {
                node* t1=find(rt,pos-1);
                Splay(t1);
                t1->rc->fa=NULL;
                t1->rc=NULL;
                t1->upt();
                n--;
            }
            else
            {
                node* t2=find(rt,pos+1);
                Splay(t2);
                t2->lc->fa=NULL;
                t2->lc=NULL;
                t2->upt();
                n--;
            }
        }
        else if(ch[1]=='M')
        {
            int l=read(),r=read();
            if(l==1&&r==n)W(rt->mn),putchar('\n');
            else if(l==1)
            {
                node* t2=find(rt,r+1);
                Splay(t2);
                W(rt->lc->mn),putchar('\n');
            }
            else if(r==n)
            {
                node* t1=find(rt,l-1);
                Splay(t1);
                W(rt->rc->mn),putchar('\n');
            }
            else 
            {
                node* t1=find(rt,l-1);
                node* t2=find(rt,r+1);
                Splay(t1);
                Splay(t2,rt);
                W(t2->lc->mn),putchar('\n');
            }
        }
        else if(ch[4]=='E')
        {
            int l=read(),r=read();
            if(l==1&&r==n)addr(rt);
            else if(l==1)
            {
                node* t2=find(rt,r+1);
                Splay(t2);
                addr(rt->lc);
            }
            else if(r==n)
            {
                node* t1=find(rt,l-1);
                Splay(t1);
                addr(rt->rc);
            }
            else 
            {
                node* t1=find(rt,l-1);
                node* t2=find(rt,r+1);
                Splay(t1);
                Splay(t2,rt);
                addr(t2->lc);
            }
        }
        else
        {
            int x=read(),y=read(),c=read();
            int l=(y-x+1);
            c%=l;
            if(c==0)continue;
            node* t1=split(y-c,y+1);
            if(x!=1)
            {
                node* t2=find(rt,x-1);
                node* t3=find(rt,x);
                Splay(t2);
                Splay(t3,rt);
                t3->lc=t1;
                t1->fa=t3;
                t3->upt();
                t2->upt();
            }
            else
            {
                node* t3=find(rt,x);
                Splay(t3);
                t3->lc=t1;
                t1->fa=t3;
                t3->upt();
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值