【题解】序列终结者

题目链接

\(splay\)维护区间加,区间翻转,区间\(max\).

维护标记,区间加标记和区间翻转标记。记住两个是同级的,都要更新。

更详细的解释请参考笔者的题解:数列。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=5e5+10;
const int inf=2e9;
int n,m,id,rt,vx[MAXN];
struct Splay_Tree{
    int val,fa,maxn,ch[2];
    int tag,siz,rev;
}tr[MAXN];
inline void pushup(int x){
    tr[x].maxn=max(tr[tr[x].ch[0]].maxn,max(tr[tr[x].ch[1]].maxn,tr[x].val));
    tr[x].siz=tr[tr[x].ch[0]].siz+tr[tr[x].ch[1]].siz+1;
}
inline int build(int l,int r,int f){
    if(l>r)return 0;int x=++id,mid=l+r>>1;
    tr[x].fa=f;tr[x].val=tr[x].maxn=vx[mid];
    tr[x].ch[0]=build(l,mid-1,x),tr[x].ch[1]=build(mid+1,r,x);
    pushup(x);return x;
}
inline void rotate(int x){
    int y=tr[x].fa,z=tr[y].fa,k=tr[y].ch[1]==x;
    tr[z].ch[tr[z].ch[1]==y]=x;tr[x].fa=z;
    tr[y].ch[k]=tr[x].ch[k^1];tr[tr[x].ch[k^1]].fa=y;
    tr[x].ch[k^1]=y;tr[y].fa=x;pushup(y);pushup(x);
}
inline void splay(int x,int g){
    while(tr[x].fa!=g){
        int y=tr[x].fa,z=tr[y].fa;
        if(z!=g)
            (tr[y].ch[0]==x)^(tr[z].ch[0]==y)?rotate(x):rotate(y);
        rotate(x);
    }
    if(!g)rt=x;
}
inline void pushdown(int x){
    int lc=tr[x].ch[0],rc=tr[x].ch[1];
    if(tr[x].tag){
        int p=tr[x].tag;
        if(lc){
            tr[lc].tag+=p;
            tr[lc].val+=p;
            tr[lc].maxn+=p;
        }
        if(rc){
            tr[rc].tag+=p;
            tr[rc].val+=p;
            tr[rc].maxn+=p;
        }
        tr[x].tag=0;
    }
    if(tr[x].rev){
        tr[x].rev=0;
        tr[lc].rev^=1;tr[rc].rev^=1;
        swap(tr[lc].ch[0],tr[lc].ch[1]);
        swap(tr[rc].ch[0],tr[rc].ch[1]);
    }
}
inline int Kth(int x){
    int u=rt;
//  if(!x)return 0;
    while(u){
        pushdown(u);
        int y=tr[u].ch[0];
        if(tr[y].siz>=x)u=y;
        else{
            x-=tr[y].siz+1;
            if(!x)return u;
            u=tr[u].ch[1];
        }
    }
    return 0;
}
inline void change_R(int x,int y){
    int L=Kth(x),R=Kth(y+2);
    splay(L,0);splay(R,L);
    int g=tr[R].ch[0];
    tr[g].rev^=1;swap(tr[g].ch[0],tr[g].ch[1]);
    pushup(R);pushup(L);
}
inline void change_A(int x,int y,int v){
    int L=Kth(x),R=Kth(y+2);
    splay(L,0);splay(R,L);
    int g=tr[R].ch[0];
    tr[g].tag+=v;tr[g].val+=v;tr[g].maxn+=v;
    pushup(R);pushup(L);
}
inline int Get(int x,int y){
    int L=Kth(x),R=Kth(y+2);
    splay(L,0);splay(R,L);
    return tr[tr[R].ch[0]].maxn;
}
int main(){
    scanf("%d%d",&n,&m);
    tr[0].maxn=vx[1]=vx[n+2]=-inf;rt=build(1,n+2,0);
    while(m--){
        int opt,L,R,X;
        scanf("%d%d%d",&opt,&L,&R);
        if(opt==1){
            scanf("%d",&X);
            change_A(L,R,X);
        }
        else if(opt==2)
            change_R(L,R);
        else if(opt==3)
            printf("%d\n",Get(L,R));
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/h-lka/p/11517539.html

时间: 2024-10-15 08:53:55

【题解】序列终结者的相关文章

[BZOJ1251]序列终结者

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

【bzoj1251】序列终结者 splay

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

【CodeVS4665】序列终结者

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

BZOJ 1251 序列终结者(Splay)

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

【BZOJ】1251: 序列终结者(splay)

http://www.lydsy.com/JudgeOnline/problem.php?id=1251 不行..为什么写个splay老是犯逗,这次又是null的mx没有赋值-maxlongint... #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #inc

BZOJ 1251: 序列终结者( splay )

先orz一下clj...我的splay跟着他写的... 这道题很普通的splay我调了这么久 T T , 就是因为 null 的值初始化为0 , 结果就挂了... -------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream>

bzoj 1251: 序列终结者 2011-12-20

1251: 序列终结者Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 650  Solved: 277[Submit][Status][Discuss]Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可

BZOJ1251&#183;序列终结者

好像不能附传送门了..这是道sb权限题.. 1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MB Description 网 上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终

伸展树复习 (bzoj 1251 序列终结者)

本来要看LCT的,确发现自己弱得连splay都忘记了,复习一发,顺便重写一发 关键点: 1. 伸展树为左小右大的二叉树,所以旋转操作不会影响树的性质 2. 区间操作为: int u = select(L - 1), v = select(R + 1); splay(u, 0); splay(v, u); //通过旋转操作把询问的区间聚集到根的右子树的左子树下 因为伸展树为左小右大的二叉树,旋转操作后的所以对于闭区间[L, R]之间的所有元素都聚集在根的右子树的左子树下 因为闭区间[L, R],