bzoj1251 序列终结者

本文深入探讨了Splay树的数据结构及其应用,并提供了一个详细的Splay树实现模板。通过具体的代码示例,讲解了Splay树的基本操作如旋转、查找等,并展示了如何利用Splay树解决区间更新和查询等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

splay模板题!!表示就用这个风格写下去好了,何时才能不面向题解编程呢

 

#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define lc no[x].ch[0]
#define rc no[x].ch[1]
using namespace std;
const int maxn=1e5+10;
const int maxs=3e5+5;
const int inf=1e9;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
struct node
{
    int val,maxx,siz,add,ch[2],fa,rev;
}no[maxn];
int root;
int n,m;
int ws(int x) {return no[no[x].fa].ch[1]==x;}//
void push_up(int x)
{
    no[x].siz=no[lc].siz+no[rc].siz+1;
    no[x].maxx=max(no[x].val,max(no[lc].maxx,no[rc].maxx));
}
void push_down(int x)
{
    if(no[x].add)
    {
        int tp=no[x].add;
        no[x].add=0;
        if(lc) no[lc].add+=tp,no[lc].maxx+=tp,no[lc].val+=tp;
        if(rc) no[rc].add+=tp,no[rc].maxx+=tp,no[rc].val+=tp;
    }
    if(no[x].rev)
    {
        swap(lc,rc);
        if(lc) no[lc].rev^=1;
        if(rc) no[rc].rev^=1;
        no[x].rev=0;
    }
}
void rotate(int x)
{
    int p=no[x].fa,q=no[p].fa,c=ws(x);
    if(q)
    {
        no[q].ch[ws(p)]=x;
    }
    no[x].fa=q;
    no[p].ch[c]=no[x].ch[c^1];no[no[p].ch[c]].fa=p;
    no[x].ch[c^1]=p;no[p].fa=x;
    push_up(p);push_up(x);
}
void splay(int x,int tar)
{
    for(;no[x].fa!=tar;rotate(x))
    {
        if(no[no[x].fa].fa!=tar)
        {
            if(ws(x)==ws(no[x].fa))rotate(no[x].fa);
            else rotate(x);
        }
    }
    if(tar==0) root = x;
}
int kth(int x)
{
    int p=0,q=root;
    while(q)
    {
        push_down(q);
        int tmp=p+no[no[q].ch[0]].siz;
        if(tmp<x&&x<=tmp+1) return q;
        if(x<=tmp) q=no[q].ch[0];
        else p=tmp+1,q=no[q].ch[1];
    }
    return -1;
}
int build(int l,int r,int fa)
{
    if(l>r) return 0;
    int x=(l+r)>>1;
    lc=build(l,x-1,x);rc=build(x+1,r,x);
    no[x].fa=fa;
    no[x].rev=no[x].add=0;
    no[x].val=no[x].maxx=0;
    push_up(x);
    return x;
}
void add(int l,int r,int v)
{
    int p=kth(l),x=kth(r+2);
    splay(p,0);
    //cout<<x<<endl;
    splay(x,root);
    //cout<<p<<"  "<<x<<endl;
    no[lc].add+=v;no[lc].maxx+=v;no[lc].val+=v;
}
void rev(int l,int r)
{
    int p=kth(l),x=kth(r+2);
    splay(p,0);splay(x,root);
    no[lc].rev^=1;
}
int getmax(int l,int r)
{
    int p=kth(l),x=kth(r+2);
    //cout<<p<<"  "<<x<<endl;
    splay(p,0);splay(x,root);
    printf("%d\n",no[lc].maxx);
}
int main()
{
    int p,q,r,s;
    n=read(),m=read();
    no[0].maxx=-inf;
    root=build(1,n+2,0);
    while(m--)
    {
        s=read();
        switch(s)
        {
            case 1:p=read();q=read();r=read();add(p,q,r);break;
            case 2:p=read();q=read();rev(p,q);break;
            case 3:p=read();q=read(); getmax(p,q);break;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值