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。

Input

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

Output

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

Sample Input
4 4
1 1 3 2
1 2 4 -1
2 1 3

3 2 4

2

#include <bits/stdc++.h>
//#include <ext/pb_ds/tree_policy.hpp>
//#include <ext/pb_ds/assoc_container.hpp>
//using namespace __gnu_pbds;
using namespace std;



#define pi acos(-1)
#define endl '\n'
#define me(x) memset(x,0,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0);
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,-1,-1,1,1};
const int dy[]={0,1,0,-1,1,-1,1,-1};
const int maxn=1e3+5;
const int maxx=1e5+100;
const double EPS=1e-7;
const int MOD=1000000007;
#define mod(x) ((x)%MOD);
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
//typedef tree<pt,null_type,less< pt >,rb_tree_tag,tree_order_statistics_node_update> rbtree;
/*lch[root] = build(L1,p-1,L2+1,L2+cnt);
    rch[root] = build(p+1,R1,L2+cnt+1,R2);中前*/
/*lch[root] = build(L1,p-1,L2,L2+cnt-1);
    rch[root] = build(p+1,R1,L2+cnt,R2-1);中后*/
long long gcd(long long a , long long b){if(b==0) return a;a%=b;return gcd(b,a);}

struct Splay_Tree
{
    struct node
    {
        int val,Max,add,Size,son[2];//add =lazy val为节点的值 Max节点最大值
        //Size 节点大小,son为儿子
        bool rev;//节点是否翻转
        void init(int _val)
        {
            val=Max=_val;
            Size=1;
            add=rev=son[0]=son[1]=0;
        }
    }T[maxx];
    int fa[maxx],root;//fa是节点的父亲,root是根
    void pushUp(int x)//从下往上更新
    {
        T[x].Max=T[x].val,T[x].Size=1;
        if(T[x].son[0])
        {
            T[x].Max=max(T[x].Max,T[T[x].son[0]].Max);
            T[x].Size+=T[T[x].son[0]].Size;
        }
        if(T[x].son[1])
        {
            T[x].Max=max(T[x].Max,T[T[x].son[1]].Max);
            T[x].Size+=T[T[x].son[1]].Size;
        }
    }
    void pushDown(int x)
    {
        if(x==0) return ;
        if(T[x].add)//如果有lazy的话
        {
            if(T[x].son[0])//左儿子更新
            {
                T[T[x].son[0]].val+=T[x].add;
                T[T[x].son[0]].Max+=T[x].add;
                T[T[x].son[0]].add+=T[x].add;
            }
            if(T[x].son[1])//右儿子更新
            {
                T[T[x].son[1]].val+=T[x].add;
                T[T[x].son[1]].Max+=T[x].add;
                T[T[x].son[1]].add+=T[x].add;
            }
            T[x].add=0;
        }
        if(T[x].rev)
        {
            if(T[x].son[0]) T[T[x].son[0]].rev^=1;
            if(T[x].son[1]) T[T[x].son[1]].rev^=1;
            swap(T[x].son[0],T[x].son[1]);
            T[x].rev=0;
        }
    }

    void Rotate(int x,int kind)
    {
        int y=fa[x],z=fa[y];
        T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y;//B
        T[x].son[kind]=y,fa[y]=x;//y
        T[z].son[T[z].son[1]==y]=x,fa[x]=z;//z
        pushUp(y);
    }//kind 为1是 !kind==0 T[y]的左儿子变成了T[x]的右儿子
    //zig zag的合并
    void Splay(int x,int goal)
    {
        if(x==goal) return ;//goal  是根
        while(fa[x]!=goal)//父亲不是根的话
        {
            int y=fa[x],z=fa[y];
            pushDown(z),pushDown(y),pushDown(x);
            int rx=T[y].son[0]==x,ry=T[z].son[0]==y;//rx==1 左儿子
            //rx==0 右儿子
            if(z==goal) Rotate(x,rx);//旋转一次
            else //旋转两次
            {
                if(rx==ry) Rotate(y,ry);
                else Rotate(x,rx);
                Rotate(x,ry);
            }
        }
        pushUp(x);
        if(goal==0) root=x;
    }
    int Select(int pos)
    {
        int u=root;
        pushDown(u);
        while(T[T[u].son[0]].Size!=pos)
        {
            if(pos<T[T[u].son[0]].Size) u=T[u].son[0];//如果小于显然在左儿子上
            else
            {
                pos-=T[T[u].son[0]].Size+1;
                u=T[u].son[1];
            }
            pushDown(u);
        }
        return u;
    }
    void update(int L,int R,int val)
    {
        int u=Select(L-1),v=Select(R+1);
        Splay(u,0);
        Splay(v,u);
        T[T[v].son[0]].Max+=val;
        T[T[v].son[0]].val+=val;
        T[T[v].son[0]].add+=val;
    }
    void Reverse(int L,int R)
    {
        int u=Select(L-1),v=Select(R+1);
        Splay(u,0);
        Splay(v,u);
        T[T[v].son[0]].rev^=1;//打标记
    }
    int query(int L,int R)
    {
        int u=Select(L-1),v=Select(R+1);
        Splay(u,0);
        Splay(v,u);
        return T[T[v].son[0]].Max;
    }
    int build(int L,int R)
    {
        if(L>R) return 0;
        if(L==R) return L;
        int mid=(L+R)>>1,sL,sR;
        T[mid].son[0]=sL=build(L,mid-1);//同线段树
        T[mid].son[1]=sR=build(mid+1,R);
        fa[sL]=fa[sR]=mid;
        pushUp(mid);
        return mid;
    }
    void init(int n)
    {
        T[0].init(-INF),T[1].init(-INF),T[n+2].init(-INF);//三个元素
        for(int i=2;i<=n+1;i++) T[i].init(0);
        root=build(1,n+2),fa[root]=0;
        fa[0]=0,T[0].son[1]=root,T[0].Size=0;
    }
};

Splay_Tree hehe;
int main()
{
    int n,m;
    cin>>n>>m;
    hehe.init(n);
    for(int i=0,a,b,c,d;i<m;i++)
    {
        cin>>a;
        if(a==1)
        {
            cin>>b>>c>>d;
            hehe.update(b,c,d);
        }
        else if(a==2)
        {
            cin>>b>>c;
            hehe.Reverse(b,c);
        }
        else
        {
            cin>>b>>c;
            printf("%d\n",hehe.query(b,c));
        }
    }
}


















内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
内容概要:本文深入探讨了利用历史速度命令(HVC)增强仿射编队机动控制性能的方法。论文提出了HVC在仿射编队控制中的潜在价值,通过全面评估HVC对系统的影响,提出了易于测试的稳定性条件,并给出了延迟参数与跟踪误差关系的显式不等式。研究为两轮差动机器人(TWDRs)群提供了系统的协调编队机动控制方案,并通过9台TWDRs的仿真和实验验证了稳定性和综合性能改进。此外,文中还提供了详细的Python代码实现,涵盖仿射编队控制类、HVC增强、稳定性条件检查以及仿真实验。代码不仅实现了论文的核心思想,还扩展了邻居历史信息利用、动态拓扑优化和自适应控制等性能提升策略,更全面地反映了群体智能协作和性能优化思想。 适用人群:具备一定编程基础,对群体智能、机器人编队控制、时滞系统稳定性分析感兴趣的科研人员和工程师。 使用场景及目标:①理解HVC在仿射编队控制中的应用及其对系统性能的提升;②掌握仿射编队控制的具体实现方法,包括控制器设计、稳定性分析和仿真实验;③学习如何通过引入历史信息(如HVC)来优化群体智能系统的性能;④探索中性型时滞系统的稳定性条件及其在实际系统中的应用。 其他说明:此资源不仅提供了理论分析,还包括完整的Python代码实现,帮助读者从理论到实践全面掌握仿射编队控制技术。代码结构清晰,涵盖了从初始化配置、控制律设计到性能评估的各个环节,并提供了丰富的可视化工具,便于理解和分析系统性能。通过阅读和实践,读者可以深入了解HVC增强仿射编队控制的工作原理及其实际应用效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值