zoukankan      html  css  js  c++  java
  • 【bzoj1251】序列终结者 Splay

    题目描述

    网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。

    输入

    第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。

    输出

    对于每个第3种操作,给出正确的回答。

    样例输入

    4 4
    1 1 3 2
    1 2 4 -1
    2 1 3
    3 2 4

    样例输出

    2


    题解

    Splay模板题。

    然而数组开到50001无故TLE调了1个小时QAQ

    由于有哨兵节点,所以开数组时要比平常多2,也就是至少要开到50003!

    下次再也不擦边开数组了。。。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int num[50005] , c[2][50005] , fa[50005] , add[50005] , rev[50005] , maxn[50005] , si[50005] , root;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0'; ch = getchar();}
        return x * f;
    }
    void pushup(int k)
    {
        int l = c[0][k] , r = c[1][k];
        maxn[k] = max(num[k] , max(maxn[l] , maxn[r]));
        si[k] = si[l] + si[r] + 1;
    }
    void pushdown(int k)
    {
        int l = c[0][k] , r = c[1][k];
        if(add[k])
        {
            if(l) num[l] += add[k] , maxn[l] += add[k] , add[l] += add[k];
            if(r) num[r] += add[k] , maxn[r] += add[k] , add[r] += add[k];
            add[k] = 0;
        }
        if(rev[k])
        {
            if(l) swap(c[0][l] , c[1][l]) , rev[l] ^= 1;
            if(r) 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;
        pushup(mid);
        c[mid > f][f] = mid;
    }
    void rotate(int &k , int x)
    {
        int y = fa[x] , z = fa[y] , l , r;
        l = (c[0][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)
    {
        while(x != k)
        {
            int 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 r)
    {
        pushdown(k);
        if(r <= si[c[0][k]]) return find(c[0][k] , r);
        else if(r > si[c[0][k]] + 1) return find(c[1][k] , r - si[c[0][k]] - 1);
        else return k;
    }
    void update(int l , int r , int v)
    {
        int lp = find(root , l) , rp = find(root , r + 2) , z;
        splay(root , lp);
        splay(c[1][root] , rp);
        z = c[0][rp];
        num[z] += v;
        maxn[z] += v;
        add[z] += v;
    }
    void rever(int l , int r)
    {
        int lp = find(root , l) , rp = find(root , r + 2) , z;
        splay(root , lp);
        splay(c[1][root] , rp);
        z = c[0][rp];
        swap(c[0][z] , c[1][z]);
        rev[z] ^= 1;
    }
    int query(int l , int r)
    {
        int lp = find(root , l) , rp = find(root , r + 2) , z;
        splay(root , lp);
        splay(c[1][root] , rp);
        z = c[0][rp];
        return maxn[z];
    }
    int main()
    {
        int n , m , k , l , r , v;
        maxn[0] = 0x80000000;
        n = read() , m = read();
        build(1 , n + 2 , 0);
        root = (n + 3) >> 1;
        while(m -- )
        {
            k = read() , l = read() , r = read();
            switch(k)
            {
                case 1: v = read(); update(l , r , v); break;
                case 2: rever(l , r); break;
                default: printf("%d
    " , query(l , r));
            }
        }
        return 0;
    }
  • 相关阅读:
    Redis使用详细教程
    Web API 强势入门指南
    log4net
    ASP.NET Web API——选择Web API还是WCF
    Hadoop RPC机制
    力扣算法:每日温度
    力扣算法:完全平方数
    力扣算法:岛屿数量
    面试总结二
    面试总结
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6400481.html
Copyright © 2011-2022 走看看