zoukankan      html  css  js  c++  java
  • 【bzoj1895】Pku3580 supermemo Splay

    题目描述

    给出一个初始序列fA1;A2;:::Ang,要求你编写程序支持如下操作: 1. ADDxyD:给子序列fAx:::Ayg的每个元素都加上D。例如对f1,2, 3,4,5g执行"ADD 241" 会得到f1,3,4,5,5g。 2. REVERSExy:将子序列fAx:::Ayg翻转。例如对f1,2,3,4,5g执 行"REVERSE 24"会得到f1,4,3,2,5g。 3. REVOLVExyT:将子序列fAx:::Ayg旋转T个单位。例如, 对f1,2,3,4,5g执行"REVOLVE 242"会得到f1,3,4,2,5g。 4. INSERTxP:在Ax后插入P。例如,对f1,2,3,4,5g执行"INSERT 24"会得到f1,2,4,3,4,5g。 5. DELETEx:删去Ax。例如,对f1,2,3,4,5g执行"DELETE 2"会得 到f1,3,4,5g。 6. MINxy:查询子序列fAx:::Ayg中的最小元素。例如,对于序列f1, 2,3,4,5g,询问"MIN 24"的返回应为2。

    输入

    第一行包含一个整数n,表示初始序列的长度。 以下n行每行包含一个整数,描述初始的序列。 接下来一行包含一个整数m,表示操作的数目。 以下m行每行描述一个操作。

    输出

    对于所有"MIN"操作,输出正确的答案,每行一个。

    样例输入

    5
    1
    2
    3
    4
    5
    2
    ADD 2 4 1
    MIN 4 5

    样例输出

    5


    题解

    Splay裸题,省选前练习模板的好机会(尽管这次没考。。。)

    写一个函数专门用来取出一段区间,可以大大减少代码量。

    注意要开long long。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 300010
    using namespace std;
    typedef long long ll;
    int fa[N] , c[2][N] , root , si[N] , rev[N] , tot;
    ll v[N] , minn[N] , add[N];
    char str[20];
    void pushup(int k)
    {
        si[k] = si[c[0][k]] + si[c[1][k]] + 1;
        minn[k] = min(v[k] , min(minn[c[0][k]] , minn[c[1][k]]));
    }
    void pushdown(int k)
    {
        int l = c[0][k] , r = c[1][k];
        if(add[k])
        {
            v[l] += add[k] , minn[l] += add[k] , add[l] += add[k];
            v[r] += add[k] , minn[r] += add[k] , add[r] += add[k];
            add[k] = 0;
        }
        if(rev[k])
        {
            swap(c[0][l] , c[1][l]) , rev[l] ^= 1;
            swap(c[0][r] , c[1][r]) , rev[r] ^= 1;
            rev[k] = 0;
        }
    }
    void build(int l , int r , int f)
    {
        if(l > r) return;
        int mid = (l + r) >> 1;
        build(l , mid - 1 , mid) , build(mid + 1 , r , mid);
        fa[mid] = f , c[mid > f][f] = mid;
        pushup(mid);
    }
    void rotate(int &k , int x)
    {
        int y = fa[x] , z = fa[y] , l , r;
        l = (c[1][y] == x);
        r = l ^ 1;
        if(y == k) k = x;
        else if(c[0][z] == y) c[0][z] = x;
        else c[1][z] = x;
        fa[x] = z , fa[y] = x , fa[c[r][x]] = y;
        c[l][y] = c[r][x] , c[r][x] = y;
        pushup(y) , pushup(x);
    }
    void splay(int &k , int x)
    {
        int y , z;
        while(x != k)
        {
            y = fa[x] , z = fa[y];
            if(y != k)
            {
                if(c[0][y] == x ^ c[0][z] == y) rotate(k , x);
                else rotate(k , y);
            }
            rotate(k , x);
        }
    }
    int find(int k , int x)
    {
        pushdown(k);
        if(x <= si[c[0][k]]) return find(c[0][k] , x);
        else if(x > si[c[0][k]] + 1) return find(c[1][k] , x - si[c[0][k]] - 1);
        else return k;
    }
    int split(int l , int r)
    {
        int a = find(root , l - 1) , b = find(root , r + 1);
        splay(root , a) , splay(c[1][root] , b);
        return c[0][c[1][root]];
    }
    void update(int l , int r , int x)
    {
        int t = split(l + 1 , r + 1);
        v[t] += x , minn[t] += x , add[t] += x;
        pushup(c[1][root]) , pushup(root);
    }
    void rever(int l , int r)
    {
        int t = split(l + 1 , r + 1);
        swap(c[0][t] , c[1][t]) , rev[t] ^= 1;
    }
    void revol(int l , int r , int x)
    {
        x %= r - l + 1;
        int t = split(r - x + 2 , r + 1);
        c[0][c[1][root]] = 0 , fa[t] = 0;
        pushup(c[1][root]) , pushup(root);
        split(l + 1 , l);
        c[0][c[1][root]] = t , fa[t] = c[1][root];
        pushup(c[1][root]) , pushup(root);
    }
    void ins(int p , int x)
    {
        split(p + 2 , p + 1);
        c[0][c[1][root]] = ++tot;
        fa[tot] = c[1][root];
        v[tot] = x;
        pushup(tot) , pushup(c[1][root]) , pushup(root);
    }
    void del(int p)
    {
        int t = split(p + 1 , p + 1);
        c[0][c[1][root]] = 0 , fa[t] = 0;
        pushup(c[1][root]) , pushup(root);
    }
    ll query(int l , int r)
    {
        int t = split(l + 1 , r + 1);
        return minn[t];
    }
    int main()
    {
        int n , m , i , x , y , z;
        ll k;
        scanf("%d" , &n);
        v[0] = v[1] = v[n + 2] = minn[0] = 0x3fffffff;
        for(i = 2 ; i <= n + 1 ; i ++ ) scanf("%d" , &v[i]);
        build(1 , n + 2 , 0);
        root = (n + 3) >> 1 , tot = n + 2;
        scanf("%d" , &m);
        while(m -- )
        {
            scanf("%s" , str);
            switch(str[0])
            {
                case 'A': scanf("%d%d%lld" , &x , &y , &k); update(x , y , k); break;
                case 'I': scanf("%d%d" , &x , &y) , ins(x , y); break;
                case 'D': scanf("%d" , &x) , del(x); break;
                case 'M': scanf("%d%d" , &x , &y); printf("%lld
    " , query(x , y)); break;
                default:
                {
                    if(str[3] == 'E') scanf("%d%d" , &x , &y) , rever(x , y);
                    else scanf("%d%d%d" , &x , &y , &z) , revol(x , y , z);
                }
            }
        }
        return 0;
    }

     

  • 相关阅读:
    UITabBarController生命周期(使用storyoard搭建)
    ios应用数据存储方式(归档)
    ios应用数据存储方式(偏好设置)
    使用picker View控件完成一个简单的选餐应用
    ios应用数据存储方式(XML属性列表-plist)
    控制器的View的创建
    控制器的创建
    权限管理具体代码实现
    gitHub相关
    初始Ajax
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6764275.html
Copyright © 2011-2022 走看看