• SPOJ 4487 Can you answer these queries VI


    SPOJ_4487

        其实这个题目和GSS1是差不多的,只不过由于有增加和删除的操作,这样用线段树就搞不定了,因此可以维护一个splay来实现这些操作。

        但是一开始我写出的程序总是TLE,而和网上一些AC的程序对照之后发现无非有两点很不同的地方,一个是他们都用了结构体,另一个是他们都用了指针。在百思不得其解之际,我把以前的若干个数组仿照一个AC的程序写成了结构体,就像下面这样:

    struct Splay
    {
        int left, right, pre, size, sum, mc, key, lc, rc;
        #define left(x) sp[x].left
        #define right(x) sp[x].right
        #define pre(x) sp[x].pre
        #define size(x) sp[x].size
        #define sum(x) sp[x].sum
        #define mc(x) sp[x].mc
        #define key(x) sp[x].key
        #define lc(x) sp[x].lc
        #define rc(x) sp[x].rc
    }sp[MAXD];

        尼玛……居然AC了……

        不知道这是不是也算底层优化……各位TLE了的同仁不妨试试写成结构体……

    #include<stdio.h>
    #include<string.h>
    #include<cstdlib>
    #define MAXD 200010
    #define INF 0x3f3f3f3f
    int N, T, a[MAXD], node;
    struct Splay
    {
        int left, right, pre, size, sum, mc, key, lc, rc;
        #define left(x) sp[x].left
        #define right(x) sp[x].right
        #define pre(x) sp[x].pre
        #define size(x) sp[x].size
        #define sum(x) sp[x].sum
        #define mc(x) sp[x].mc
        #define key(x) sp[x].key
        #define lc(x) sp[x].lc
        #define rc(x) sp[x].rc
    }sp[MAXD];
    int Max(int x, int y)
    {
        return x > y ? x : y;
    }
    void newnode(int &cur, int v)
    {
        cur = ++ node;
        size(cur) = 1;
        key(cur) = sum(cur) = mc(cur) = lc(cur) = rc(cur) = v;
        left(cur) = right(cur) = 0;
    }
    void update(int cur)
    {
        int ls = left(cur), rs = right(cur);
        size(cur) = size(ls) + size(rs) + 1;
        sum(cur) = sum(ls) + sum(rs) + key(cur);
        mc(cur) = Max(rc(ls), 0) + key(cur) + Max(lc(rs), 0);
        mc(cur) = Max(mc(cur), Max(mc(ls), mc(rs)));
        lc(cur) = Max(lc(ls), sum(ls) + key(cur) + Max(lc(rs), 0));
        rc(cur) = Max(rc(rs), sum(rs) + key(cur) + Max(rc(ls), 0));
    }
    void leftrotate(int cur)
    {
        int k = right(cur), fa = pre(cur);
        right(cur) = left(k);
        pre(right(cur)) = cur;
        left(k) = cur;
        pre(cur) = k;
        pre(k) = fa;
        right(fa) == cur ? right(fa) = k : left(fa) = k;
        update(cur);
    }
    void rightrotate(int cur)
    {
        int k = left(cur), fa = pre(cur);
        left(cur) = right(k);
        pre(left(cur)) = cur;
        right(k) = cur;
        pre(cur) = k;
        pre(k) = fa;
        right(fa) == cur ? right(fa) = k : left(fa) = k;
        update(cur);
    }
    void build(int &cur, int x, int y, int fa)
    {
        int mid = (x + y) >> 1;
        newnode(cur, a[mid]);
        pre(cur) = fa;
        if(x == y)
            return ;
        if(x < mid)
            build(left(cur), x, mid - 1, cur);
        if(mid < y)
            build(right(cur), mid + 1, y, cur);
        update(cur);
    }
    void splay(int x, int goal)
    {
        int y, z;
        for(;;)
        {
            if((y = pre(x)) == goal)
                break;
            if((z = pre(y)) == goal)
                right(y) == x ? leftrotate(y) : rightrotate(y);
            else
            {
                if(right(z) == y)
                    right(y) == x ? (leftrotate(z), leftrotate(y)) : (rightrotate(y), leftrotate(z));
                else
                    left(y) == x ? (rightrotate(z), rightrotate(y)) : (leftrotate(y), rightrotate(z));
            }
        }
        if(goal == 0)
            T = x;
        update(x);
    }
    void rotateto(int k, int goal)
    {
        int cur = T, n;
        for(;;)
        {
            n = size(left(cur)) + 1;
            if(n == k)
                break;
            if(k < n)
                cur = left(cur);
            else
                k -= n, cur = right(cur);
        }
        splay(cur, goal);
    }
    void init()
    {
        int i;
        for(i = 1; i <= N; i ++)
            scanf("%d", &a[i]);
        node = size(0) = sum(0) = 0;
        mc(0) = lc(0) = rc(0) = -INF;
        newnode(T, 0), newnode(right(T), 0);
        pre(right(T)) = T;
        key(T) = key(right(T)) = 0;
        if(N)
            build(left(right(T)), 1, N, right(T));
        update(right(T)), update(T);
    }
    void Delete(int x)
    {
        rotateto(x, 0), rotateto(x + 2, T);
        left(right(T)) = 0;
        update(right(T)), update(T);
    }
    void Insert(int x, int y)
    {
        rotateto(x, 0), rotateto(x + 1, T);
        newnode(left(right(T)), y);
        pre(node) = right(T);
        update(right(T)), update(T);
    }
    void Replace(int x, int y)
    {
        rotateto(x + 1, 0);
        key(T) = y;
        update(T);
    }
    void Query(int x, int y)
    {
        rotateto(x, 0), rotateto(y + 2, T);
        printf("%d\n", mc(left(right(T))));
    }
    void solve()
    {
        int i, q, x, y;
        char op[5];
        scanf("%d", &q);
        for(i = 0; i < q; i ++)
        {
            scanf("%s", op);
            if(op[0] == 'D')
            {
                scanf("%d", &x);
                Delete(x);
            }
            else
            {
                scanf("%d%d", &x, &y);
                if(op[0] == 'I')
                    Insert(x, y);
                else if(op[0] == 'R')
                    Replace(x, y);
                else
                    Query(x, y);
            }
        }
    }
    int main()
    {
        while(scanf("%d", &N) == 1)
        {
            init();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    docker run 参数含义
    java——数组队列 ArrayQueue
    java——数组栈 ArrayStack
    java——时间复杂度、动态数组
    java——异常类、异常捕获、finally、异常抛出、自定义异常
    java——变量
    java——虚拟机、线程
    java——内部类
    java——object类
    java——抽象类、接口、二者区别
  • 原文地址:https://www.cnblogs.com/staginner/p/2529405.html
Copyright © 2020-2023  润新知