hdu 4453 Looploop(Splay或者三个双端队列)

题意:有N个数字围成一个圈,有M个操作,操作类型有六种:(1)“add x",从当前指针位置开始的顺时针K2个数加上x。(2)"reverse",翻转,从当前指针指针位置开始的顺时针的K2个数。(3)"insert x",在当前指针位置的顺时候方向插入一个数x。(4)”delete“,删除当前指针所指的数。(5)"move x”,如果x=1,指针逆时针旋转,如果x=2,顺时针旋转。(6)“query",查询指针所指向的数的值。

Splay的作法就不说了。还可以有三个双端队列加两个标记搞定,方法,是第一个双端队列que1维护前K1个数,第二个que2维护第K1+1到第K2个数,第三个que3维护接下的数,标记add,表示que1和que2里的数要加上多少,标记head,表示que1是否被翻转过。

Splay(姿势1):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;

typedef long long LL;
typedef pair<int,int> PII;

#define LL(x)    (ch[x][0])
#define RR(x)    (ch[x][1])
#define Kt       (ch[ ch[Rt][1] ][0])
#define MID(a,b) (a+((b-a)>>1))

const int N=1e6+5;

int n,m,k1,k2;
int a[N/2];

struct SplayTree
{
    int Rt,top;
    int pre[N],sz[N],ch[N][2];

    int key[N],add[N],pos;
    bool flip[N];

    inline void Link(int x,int y,int f)
    {
        pre[x]=y; if(y) ch[y][f]=x;
    }
    inline void Rotate(int x,int f)
    {
        int y=pre[x],z=pre[y];

        PushDown(y); PushDown(x);

        Link(x,z,RR(z)==y);
        Link(ch[x][f],y,!f);
        Link(y,x,f);

        PushUp(y);
    }
    inline void Splay(int x,int goal)
    {
        while(pre[x]!=goal)
        {
            int y=pre[x],z=pre[y];
            int cx=(LL(y)==x),cy=(LL(z)==y);
            if(z==goal) Rotate(x,cx);
            else
            {
                if(cx==cy) Rotate(y,cy);
                else Rotate(x,cx);
                Rotate(x,cy);
            }
        }
        PushUp(x);
        if(goal==0) Rt=x;
    }
    inline void Select(int K,int goal)
    {
        int x=Rt;
        PushDown(x);
        while(1)
        {
            if(sz[LL(x)]>=K) x=LL(x);
            else if(sz[LL(x)]+1==K) break;
            else K-=sz[LL(x)]+1,x=RR(x);
            PushDown(x);
        }
        Splay(x,goal);
    }

    inline void fun_add(int x,int valu)
    {
        add[x]+=valu;
        key[x]+=valu;
    }
    inline void fun_flip(int x)
    {
        flip[x]^=1;
        swap(LL(x),RR(x));
    }
    inline void PushDown(int x)
    {
        if(add[x])
        {
            fun_add(LL(x),add[x]);
            fun_add(RR(x),add[x]);
            add[x]=0;
        }
        if(flip[x])
        {
            fun_flip(LL(x));
            fun_flip(RR(x));
            flip[x]=0;
        }
    }
    inline void PushUp(int x)
    {
        sz[x]=1+sz[LL(x)]+sz[RR(x)];
    }
    inline void Add(int x)
    {
        Select(1,0); Select(k2+2,Rt);
        fun_add(Kt,x);
    }
    inline void Reverse()
    {
        Select(1,0); Select(k1+2,Rt);
        fun_flip(Kt);
    }
    inline void Insert(int x,int pos)
    {
        Select(pos,0); Select(pos+1,Rt);
        addNode(x,Kt,RR(Rt));
        PushUp(RR(Rt)); PushUp(Rt);
    }
    inline int Delete(bool top)
    {
        int valu;
        if(top)
        {
            Select(1,0);    Select(3,Rt);
            valu=key[Kt];
            Kt=0;
            PushUp(RR(Rt)); PushUp(Rt);
        }
        else
        {
            int len=sz[Rt];
            Select(len-2,0);Select(len,Rt);
            valu=key[Kt];
            Kt=0;
            PushUp(RR(Rt)); PushUp(Rt);
        }
        return valu;
    }
    inline void Move(int x)
    {
        if(x==1)
        {
            int valu=Delete(0);
            Insert(valu,1);
        }
        else
        {
            int valu=Delete(1);
            Insert(valu,sz[Rt]-1);
        }
    }
    inline void Query()
    {
        Select(2,0);
        printf("%d\n",key[Rt]);
    }

//    void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }
//    void Travel(int x)
//    {
//        if(x==0) return;
//
//        PushDown(x);
//        Travel(LL(x));
//        printf("node:%d,pre:%d,sz:%d,LL:%d,RR:%d,key:%d\n",
//               x,pre[x],sz[x],LL(x),RR(x),key[x]);
//        Travel(RR(x));
//    }

    void addNode(int valu,int &x,int f)
    {
        x=++top;
        pre[x]=f; sz[x]=1; LL(x)=RR(x)=0;

        key[x]=valu; add[x]=flip[x]=0;
    }
    void build(int lft,int rht,int &x,int f)
    {
        if(lft>rht) return;

        int mid=MID(lft,rht);
        addNode(a[mid],x,f);
        build(lft,mid-1,LL(x),x);
        build(mid+1,rht,RR(x),x);
        PushUp(x);
    }
    void init()
    {
        Rt=top=0;
        pre[0]=sz[0]=LL(0)=RR(0)=0;

        addNode(0,Rt,0);    addNode(0,RR(Rt),Rt);
        build(0,n-1,Kt,RR(Rt));
        PushUp(RR(Rt));     PushUp(Rt);
    }
}spt;
int main()
{
    int t_cnt=0;
    while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF)
    {
        if(n==0&&m==0&&k1==0&&k2==0) break;

        for(int i=0;i<n;i++) scanf("%d",&a[i]);

        spt.init();

        printf("Case #%d:\n",++t_cnt);

        char op[100]; int x;
        while(m--)
        {
            scanf("%s",op);
            if(op[0]=='a')
            {
                scanf("%d",&x); spt.Add(x);
            }
            else if(op[0]=='r') spt.Reverse();
            else if(op[0]=='i')
            {
                scanf("%d",&x); spt.Insert(x,2);
            }
            else if(op[0]=='d') spt.Delete(1);
            else if(op[0]=='m')
            {
                scanf("%d",&x); spt.Move(x);
            }
            else spt.Query();
        }
    }
    return 0;
}

Spaly(姿势2):

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define LL(x) (ch[x][0])
#define RR(x) (ch[x][1])
#define Kt    (ch[ ch[Rt][1] ][0])
#define MID(a,b)   (a+((b-a)>>1))

const int N=1e6+5;

int a[N/2];
int n,m,K1,K2,pos;

struct SplayTree
{
    int Rt,top;
    int sz[N],pre[N],ch[N][2];

    bool flip[N];
    int key[N],add[N];

    inline void Link(int x,int y,int f)
    {
        pre[x]=y; if(y) ch[y][f]=x;
    }
    inline void Rotate(int x,int f)
    {
        int y=pre[x],z=pre[y];

        PushDown(y); PushDown(x);
        Link(x,z,RR(z)==y);
        Link(ch[x][f],y,!f);
        Link(y,x,f);
        PushUp(y);
    }
    inline void Splay(int x,int goal)
    {
        while(pre[x]!=goal)
        {
            int y=pre[x],z=pre[y];
            int cx=(LL(y)==x),cy=(LL(z)==y);
            if(z==goal) Rotate(x,cx);
            else
            {
                if(cx==cy) Rotate(y,cy);
                else Rotate(x,cx);
                Rotate(x,cy);
            }
        }
        PushUp(x);
        if(goal==0) Rt=x;
    }
    inline void Select(int K,int goal)
    {
        int x=Rt;
        PushDown(x);
        while(1)
        {
            if(sz[LL(x)]>=K) x=LL(x);
            else if(1+sz[LL(x)]==K) break;
            else K-=sz[LL(x)]+1,x=RR(x);
            PushDown(x);
        }
        Splay(x,goal);
    }

    inline void fun_add(int x,int valu)
    {
        key[x]+=valu;
        add[x]+=valu;
    }
    inline void fun_flip(int x)
    {
        flip[x]^=1;
        swap(LL(x),RR(x));
    }
    inline void PushUp(int x)
    {
        sz[x]=1+sz[LL(x)]+sz[RR(x)];
    }
    inline void PushDown(int x)
    {
        if(add[x])
        {
            fun_add(LL(x),add[x]);
            fun_add(RR(x),add[x]);
            add[x]=0;
        }
        if(flip[x])
        {
            fun_flip(LL(x)); fun_flip(RR(x));
            flip[x]=0;
        }
    }
    inline void Add(int st,int ed,int valu)
    {
        Select(st-1,0); Select(ed+1,Rt);
        fun_add(Kt,valu);
    }
    inline void Reverse(int st,int ed)
    {
        Select(st-1,0); Select(ed+1,Rt);
        fun_flip(Kt);
    }
    inline void Insert(int pos,int valu)
    {
        Select(pos,0);  Select(pos+1,Rt);
        addNode(valu,Kt,RR(Rt));
        PushUp(RR(Rt)); PushUp(Rt);
    }
    inline void Delete(int pos)
    {
        Select(pos-1,0); Select(pos+1,Rt);
        Kt=0;  PushUp(RR(Rt)); PushUp(Rt);
    }
    inline void Query(int pos)
    {
        Select(pos,0);
        printf("%d\n",key[Rt]);
    }
    inline void Move(int len)
    {
        pos-=len;
        Select(1,0);    Select(2+len,Rt);
        int r1=Kt;      Kt=0;
        PushUp(RR(Rt)); PushUp(Rt);

        Select(sz[Rt]-1,0); Select(sz[Rt],Rt);
        Link(r1,RR(Rt),0);
        PushUp(RR(Rt)); PushUp(Rt);
    }

    inline void addNode(int valu,int &x,int f)
    {
        x=++top;

        sz[x]=1; pre[x]=f; LL(x)=RR(x)=0;

        key[x]=valu; add[x]=flip[x]=0;
    }
    void build(int lft,int rht,int &x,int f)
    {
        if(lft>rht) return;

        int mid=MID(lft,rht);
        addNode(a[mid],x,f);
        build(lft,mid-1,LL(x),x);
        build(mid+1,rht,RR(x),x);
        PushUp(x);
    }
    void init()
    {
        Rt=top=0;

        addNode(0,Rt,0); addNode(0,RR(Rt),Rt);

        build(0,n-1,Kt,RR(Rt));
        PushUp(RR(Rt));  PushUp(Rt);
    }

//    void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }
//    void Travel(int x)
//    {
//        if(x==0) return;
//        PushDown(x);
//        Travel(LL(x));
//        printf("node:%d,sz:%d,pre:%d,LL:%d,RR:%d,key:%d\n",
//               x,sz[x],pre[x],LL(x),RR(x),key[x]);
//        Travel(RR(x));
//    }
}spt;
void deal(int &pos,int len)
{
    if(pos<=1) pos=len-1;
    if(pos>=len) pos=2;
}
int main()
{
    freopen("in.txt","r",stdin);

    int t_cnt=0;
    while(scanf("%d%d%d%d",&n,&m,&K1,&K2)!=EOF)
    {
        if(n==0&&m==0&&K1==0&&K2==0) break;

        for(int i=0;i<n;i++) scanf("%d",&a[i]);

        spt.init(); pos=2;

        printf("Case #%d:\n",++t_cnt);

        char op[100]; int x;
        while(m--)
        {
            int len=spt.sz[spt.Rt];
            scanf("%s",op);
            if(op[0]=='a')
            {
                scanf("%d",&x);
                if(pos+K2>len) spt.Move(pos+K2-len);
                spt.Add(pos,pos+K2-1,x);
            }
            else if(op[0]=='r')
            {
                if(pos+K1>=len) spt.Move(pos+K1-len);
                spt.Reverse(pos,pos+K1-1);
            }
            else if(op[0]=='i')
            {
                scanf("%d",&x); spt.Insert(pos,x);
            }
            else if(op[0]=='d')
            {
                spt.Delete(pos);
                deal(pos,spt.sz[spt.Rt]);
            }
            else if(op[0]=='m')
            {
                scanf("%d",&x);
                if(x==1) pos--;
                else pos++;
                deal(pos,len);
            }
            else if(op[0]=='q') spt.Query(pos);
//            spt.Debug();
        }
    }
    return 0;
}


三个双端队列:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;

typedef long long LL;
typedef pair<int,int> PII;

const int N=1e5+5;

int n,m,k1,k2;
int a[N];

struct Looploop
{
    deque<int> que1,que2,que3;

    int add,head;
    void init()
    {
        add=0; head=1;
        while(!que1.empty()) que1.pop_back();
        while(!que2.empty()) que2.pop_back();
        while(!que3.empty()) que3.pop_back();

        for(int i=0;i<k1;i++)   que1.push_back(a[i]);
        for(int i=k1;i<k2;i++)  que2.push_back(a[i]);
        for(int i=k2;i<n ;i++)  que3.push_back(a[i]);
    }
    void Add(int x){ add+=x; }
    void Reverse() { head=!head; }
    void Insert(int x)
    {
        if(head)
        {
            que3.push_back(que1.front()+add);  que1.pop_front();
            que1.push_front(x-add);
        }
        else
        {
            que3.push_back(que1.back()+add);   que1.pop_back();
            que1.push_back(x-add);
        }
        Move(1);
    }
    void Delete()
    {
        if(head)
        {
            que1.pop_front();
            que1.push_back(que2.front());
        }
        else
        {
            que1.pop_back();
            que1.push_front(que2.front());
        }
        que2.pop_front();
        que2.push_back(que3.front()-add);
        que3.pop_front();
    }
    void Move(int x)
    {
        if(x==2)
        {
            if(head)
            {
                que3.push_back(que1.front()+add);  que1.pop_front();
                que2.push_back(que3.front()-add);  que3.pop_front();
                que1.push_back(que2.front());       que2.pop_front();
            }
            else
            {
                que3.push_back(que1.back()+add);   que1.pop_back();
                que2.push_back(que3.front()-add);  que3.pop_front();
                que1.push_front(que2.front());       que2.pop_front();
            }
        }
        else
        {
            if(head)
            {
                que1.push_front(que3.back()-add);  que3.pop_back();
                que2.push_front(que1.back());       que1.pop_back();
                que3.push_front(que2.back()+add);  que2.pop_back();
            }
            else
            {
                que1.push_back(que3.back()-add);   que3.pop_back();
                que2.push_front(que1.front());      que1.pop_front();
                que3.push_front(que2.back()+add);  que2.pop_back();
            }
        }
    }
    void query()
    {
        if(head) printf("%d\n",que1.front()+add);
        else printf("%d\n",que1.back()+add);
    }
    void Display()
    {
        printf("head:%d,add:%d\n",head,add);

        printf("que1: ");
        int len=(int)que1.size();
        if(head)
        {
            for(int i=0;i<len;i++) printf("%d ",que1[i]+add);puts("");
        }
        else
        {
            for(int i=len-1;i>=0;i--) printf("%d ",que1[i]+add);puts("");
        }

        printf("que2: ");
        len=(int)que2.size();
        for(int i=0;i<len;i++) printf("%d ",que2[i]+add);puts("");

        printf("que3: ");
        len=(int)que3.size();
        for(int i=0;i<len;i++) printf("%d ",que3[i]);puts("");
    }
}loop;
int main()
{
    int t_cnt=0;
    while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF)
    {
        if(n==0&&m==0&&k1==0&&k2==0) break;

        for(int i=0;i<n;i++) scanf("%d",&a[i]);

        loop.init();
        printf("Case #%d:\n",++t_cnt);

        int tmp;
        char op[100];
        while(m--)
        {
            scanf("%s",op);
            if(op[0]=='a')
            {
                scanf("%d",&tmp);
                loop.Add(tmp);
            }
            else if(op[0]=='r') loop.Reverse();
            else if(op[0]=='i')
            {
                scanf("%d",&tmp);
                loop.Insert(tmp);
            }
            else if(op[0]=='d') loop.Delete();
            else if(op[0]=='m')
            {
                scanf("%d",&tmp);
                loop.Move(tmp);
            }
            else loop.query();
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/shiqi_614/article/details/11101771
今日推荐