zoukankan      html  css  js  c++  java
  • 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
    ",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;
    }
    既然选择了远方,便只顾风雨兼程
  • 相关阅读:
    mysql复制那点事
    全排列问题
    56. Merge Interval
    2. Add Two Numbers
    20. Valid Parentheses
    121. Best Time to Buy and Sell Stock
    120. Triangle
    96. Unique Binary Search Trees
    91. Decode Ways
    72. Edit Distance
  • 原文地址:https://www.cnblogs.com/lindalee/p/6952148.html
Copyright © 2011-2022 走看看