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;
    }
    既然选择了远方,便只顾风雨兼程
  • 相关阅读:
    1. 马尔科夫决策过程
    梯度下降法、随机梯度下降法、小批量梯度下降法
    计算曲线与坐标轴的面积
    鼠标进入,显示div
    codewar
    Django firstDay
    C#学习之关于lock
    winfrom 界面中表格数据修改及刷新(DEV)
    SVN 分支合并 版本控制
    wpf 绑定非元素对象
  • 原文地址:https://www.cnblogs.com/lindalee/p/6952148.html
Copyright © 2011-2022 走看看