HDU - 4453 splay

题意:有n个数排成环,m个操作1.当前位置后k2个加一个数,2当前位置后k1个翻转,3当前位置后面插入一个数,4删除当前位置的数,5将当前位置前移或后移6查询当前位置的权值
题解:splay裸题,唯一麻烦的是翻转操作,因为可能不连续,单独考虑即可

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
//#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define fin freopen("a.txt","r",stdin)
#define fout freopen("c.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
template<typename T>
inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>
inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;

const double eps=1e-8;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=500000+10,maxn=200000+10,inf=0x3f3f3f3f;

int n;
struct Splay{
    struct Node{
        Node* ch[2];
        int v,s;
        int flip,lazy;
        int cmp(int x)const{
            int d = x - ch[0]->s;
            if(d==1)return -1;
            return d<=0 ? 0:1;
        }
        void maintain()
        {
            s = 1 + ch[0]->s + ch[1]->s;
        }
        void pushdown()
        {
            if(flip)
            {
                flip=0;
                swap(ch[0],ch[1]);
                ch[0]->flip = !(ch[0]->flip);
                ch[1]->flip = !(ch[1]->flip);
            }
            if(lazy!=0)
            {
                if(ch[0]->s!=0)ch[0]->v+=lazy;
                if(ch[1]->s!=0)ch[1]->v+=lazy;
                ch[0]->lazy+=lazy;
                ch[1]->lazy+=lazy;
                lazy=0;
            }
        }
    };
    Node pp[N];
    int cnt;
    Node* null;
    void Rotate(Node* &o,int d)
    {
        Node* k = o->ch[d^1];
        o->ch[d^1] = k->ch[d];
        k->ch[d] = o;
        o->maintain();k->maintain();
        o = k;
    }
    void splay(Node* &o,int k)
    {
        o->pushdown();
        int d = o->cmp(k);
        if(d==1)k -= o->ch[0]->s + 1;
        if(d!=-1)
        {
            Node* p = o->ch[d];
            p->pushdown();
            int d2 = p->cmp(k);
            int k2 = (d2==0 ? k:k-p->ch[0]->s-1);
            if(d2!=-1)
            {
                splay(p->ch[d2],k2);
                if(d==d2)Rotate(o,d^1);
                else Rotate(o->ch[d],d);
            }
            Rotate(o,d^1);
        }
    }
    Node* Merge(Node* left,Node* right)
    {
        splay(left,left->s);
        left->ch[1] = right;
        left->maintain();
        return left;
    }
    void split(Node* o,int k,Node* &left,Node* &right)
    {
        splay(o,k);
        right = o->ch[1];
        o->ch[1] = null;
        left = o;
        left->maintain();
    }
    Node *root,*left,*right;
    void init(int sz)
    {
        cnt=0;
        null=&pp[++cnt];
        null->s=0;
        root=&pp[++cnt];
        scanf("%d",&root->v);
        root->flip=root->lazy=0;root->s=1;
        root->ch[0]=root->ch[1]=null;
        root->maintain();
        Node* p;
        for(int i=2;i<=sz;i++)
        {
            p=&pp[++cnt];
            scanf("%d",&p->v);
            p->s=p->flip=0;
            p->lazy=0;
            p->ch[0]=root,p->ch[1]=null;
            root=p;
            root->maintain();
        }
    }
    void ins(int pos,int x)
    {
        Node *mid;mid=&pp[++cnt];
        mid->v=x;
        mid->flip=0,mid->lazy=0;
        mid->ch[0]=mid->ch[1]=null;
        mid->maintain();
        if(pos==root->s)root=Merge(root,mid);
        else
        {
            split(root,pos,left,right);
            root=Merge(left,Merge(mid,right));
//            print(root);
        }
    }
    void del(int pos)
    {
        if(pos==1)
        {
            split(root,1,left,right);
            root=right;
        }
        else if(pos==n)
        {
            split(root,pos-1,left,right);
            root=left;
        }
        else
        {
            split(root,pos,left,right);
            Node *mid;
            split(left,pos-1,left,mid);
            root=Merge(left,right);
        }
    }
    int change(int l,int r,int x,int op)//1-add,2-rev,3-query
    {
        int ans=0;
        if(l==1&&r==root->s)
        {
            if(op==1)
            {
                root->lazy+=x;
                root->v+=x;
            }
            else if(op==2)root->flip^=1;
            else ans=root->v;
        }
        else if(l==1&&r!=root->s)
        {
            split(root,r,left,right);
            if(op==1)
            {
                left->lazy+=x;
                left->v+=x;
            }
            else if(op==2)left->flip^=1;
            else ans=left->v;
            root=Merge(left,right);
        }
        else if(l!=1&&r==root->s)
        {
            split(root,l-1,left,right);
            if(op==1)
            {
                right->lazy+=x;
                right->v+=x;
            }
            else if(op==2)right->flip^=1;
            else ans=right->v;
            root=Merge(left,right);
        }
        else
        {
            split(root,r,left,right);
            Node *mid;
            split(left,l-1,left,mid);
            if(op==1)
            {
                mid->lazy+=x;
                mid->v+=x;
            }
            else if(op==2)mid->flip^=1;
            else ans=mid->v;
            root=Merge(left,Merge(mid,right));
        }
        return ans;
    }
    void rev(int l1,int r1,int l2,int r2)
    {
//        printf("%d %d %d %d\n",l1,r1,l2,r2);
        if(r1-l1==r2-l2)
        {
            split(root,l2-1,left,right);
            Node *mid;
            split(left,r1,left,mid);
            left->flip^=1,right->flip^=1;
            root=Merge(right,Merge(mid,left));
        }
        else if(r1-l1>r2-l2)
        {
            int len=r2-l2+1,te=r1-len+1;
//            printf("%d %d\n",len,te);
            Node *mid1;Node *mid2;
            split(root,l2-1,left,right);
            split(left,r1,left,mid2);
            split(left,te-1,left,mid1);
            mid1->flip^=1;
            left->flip^=1;right->flip^=1;
            root=Merge(Merge(left,right),Merge(mid2,mid1));
        }
        else
        {
            int len=r1-l1+1,te=l2+len-1;
            Node *mid1;Node *mid2;
            split(root,te,left,right);
            split(left,l2-1,left,mid2);
            split(left,r1,left,mid1);
            mid2->flip^=1;
            left->flip^=1;right->flip^=1;
            root=Merge(Merge(mid2,mid1),Merge(left,right));
        }
    }
    void print(Node *o)
    {
        o->pushdown();
        printf("%d %d %d++\n",o->ch[0]->v,o->v,o->ch[1]->v);
        if(o->ch[0]!=null)print(o->ch[0]);
        if(o->ch[1]!=null)print(o->ch[1]);
    }
}sp;
char op[10];
int main()
{
    int cas=0,m,k1,k2;
    while(~scanf("%d%d%d%d",&n,&m,&k1,&k2))
    {
        if(!n&&!m&&!k1&&!k2)break;
        int now=1;
        sp.init(n);
        printf("Case #%d:\n",++cas);
        while(m--)
        {
            scanf("%s",op);
            if(op[0]=='a')
            {
                int x;scanf("%d",&x);
                if(now+k2-1>n)
                {
                    sp.change(now,n,x,1);
                    sp.change(1,now+k2-n-1,x,1);
                }
                else sp.change(now,now+k2-1,x,1);
            }
            else if(op[0]=='r')
            {
                if(now+k1-1>n)sp.rev(1,now+k1-n-1,now,n);
                else sp.change(now,now+k1-1,0,2);
            }
            else if(op[0]=='i')
            {
                int x;scanf("%d",&x);
                sp.ins(now,x);n++;
            }
            else if(op[0]=='d')
            {
                sp.del(now);
                if(now==n)now=1;
                n--;
            }
            else if(op[0]=='m')
            {
                int x;scanf("%d",&x);
                if(x==1)
                {
                    now--;
                    if(now<=0)now=n;
                }
                else
                {
                    now++;
                    if(now>n)now=1;
                }
            }
            else printf("%d\n",sp.change(now,now,0,3));
        }
    }
    return 0;
}
/********************
5 100 3 4
1 2 3 4 5
move 1
reverse
query
********************/
posted @ 2018-10-16 19:02  walfy  阅读(257)  评论(0编辑  收藏  举报