Splay维护区间

Description

给你一个长度为N的序列{ai}和M个操作 
1.查询第k个数的值 
2.将第k个数增加d 
3.查询一段区间的和 
4.查询一段区间的最大值 
5.将一段区间镜面翻转(例如序列{1,2,3,4,5,6},将从2到5的区间翻转后得到序列{1,5,4,3,2,6}) 
对于除操作2,5以外的操作,输出相应的答案

Input

第一行两个正整数N,M 
第二行N个整数,为初始的序列 
第三行到底M+2行,每行若干个整数 
·如果第一个数为1,那么后面一个正整数k,表示查询第k个数的值 
·如果第一个数是2,那么后面两个正整数k,d,表示将ak增加d 
·如果第一个数为3,那么后面两个正整数l,r,表示查询从al到ar的区间和 
·如果第一个数为4,那么后面两个正整数l,r,表示查询从al到ar的最大值 
·如果第一个数为5,那么后面两个正整数l,r,表示翻转从al到ar的这个区间

Output

除操作2,5外每个操作输出占一行,一个整数,为本次提问的答案

Sample Input

6 8
1 2 3 4 5 6
1 4
3 2 5
4 2 2
5 2 5
3 1 3
5 2 5
2 5 1
4 1 6

Sample Output

4
14
2
10
6

Hint

2<=N<=100000 
1<=M<=100000 
原序列1<=ai<=1000 
每次1<=k<=N,1<=l<=r<=N,1<=d<=1000 


【分析】

好吧这是一道模版题。

注意当前当前节点打标记时,状态要为已更新。


【代码】

//Ciocio's code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <deque>
#include <utility>
#include <functional>
#include <vector>

using namespace std;

#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(int i=(b);i>=(a);--i)
#define INF (~0U>>3)
#define sf scanf
#define pf printf

#define MAXN 100010

struct SplayNode{
    #define node SplayNode
    node* ch[2];
    node* fa;
    int sz;
    int val;
    int max;
    int sum;
    bool lazy;
    node(){
        ch[0]=ch[1]=fa=NULL;
        sz=val=max=sum=lazy=0;
    }
}*null=new node(),*root;
node Pool[MAXN];
node* New=Pool;
int N,M;
int A[MAXN];

void Read(int& x){
    char tt=getchar();
    while(tt<'0'||'9'<tt) tt=getchar();
    for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
}

void Updata(node* r){
    r->sz=r->ch[0]->sz+r->ch[1]->sz+1;
    r->max=r->sum=r->val;
    if(r->ch[0]!=null){
        r->max=max(r->max,r->ch[0]->max);
        r->sum+=r->ch[0]->sum;
    }
    if(r->ch[1]!=null){
        r->max=max(r->max,r->ch[1]->max);
        r->sum+=r->ch[1]->sum;
    }
}

void Putdown(node* r){
    node* lc=r->ch[0];
    node* rc=r->ch[1];
    lc->lazy=!lc->lazy;
    rc->lazy=!rc->lazy;
    swap(lc->ch[0],lc->ch[1]);
    swap(rc->ch[0],rc->ch[1]);
    r->lazy=false;
}

void Rotate(node* r,bool k){
    node* t=r->fa;
    t->ch[!k]=r->ch[k];
    r->ch[k]->fa=t;
    r->fa=t->fa;
    if(t==t->fa->ch[0]) t->fa->ch[0]=r;
    else t->fa->ch[1]=r;
    r->ch[k]=t;
    t->fa=r;
    Updata(t);
    Updata(r);
    if(root==t) root=r;
}

node* Get(int val,node* fa){
    New->ch[0]=New->ch[1]=null;
    New->fa=fa;
    New->val=New->max=New->sum=val;
    New->sz=1;
    New->lazy=false;
    return New++;
}

#define Mid ((Left+Right)>>1)
node* Build(node* f,int Left,int Right){
    if(Right<Left) return null;
    if(Left==Right){
        node* p=Get(A[Left],f);
        return p;
    }
    node* p=Get(A[Mid],f);
    p->ch[0]=Build(p,Left,Mid-1);
    p->ch[1]=Build(p,Mid+1,Right);
    Updata(p);
    return p;
}

void Splay(node* r,node* f){
    while(r->fa!=f){
        if(r->fa->fa==f){
            if(r==r->fa->ch[0]) Rotate(r,1);
            else Rotate(r,0);
        }
        else{
            node* a=r->fa;
            node* b=a->fa;
            if(a==b->ch[0]){
                if(r==a->ch[0])
                    Rotate(a,1),Rotate(r,1);
                else
                    Rotate(r,0),Rotate(r,1);
            }
            else{
                if(r==a->ch[1])
                    Rotate(a,0),Rotate(r,0);
                else
                    Rotate(r,1),Rotate(r,0);
            }
        }
    }
}

node* Ask(node* r,int k){
    if(r->lazy) Putdown(r);
    if(k==r->ch[0]->sz+1) return r;
    if(k<=r->ch[0]->sz)
        return Ask(r->ch[0],k);
    else
        return Ask(r->ch[1],k-r->ch[0]->sz-1);
}

void Init(){
    Read(N);Read(M);
    rep(i,2,N+1) Read(A[i]);
    N+=2;
    A[1]=A[N]=INF;
    root=Build(null,1,N);
}

void Solve(){
    int T,k,d,l,r;
    while(M--){
        Read(T);
        if(T==1){
            Read(k);
            pf("%d\n",Ask(root,k+1)->val);
        }
        else if(T==2){
            Read(k);
            Read(d);
            Splay(Ask(root,k+1),null);
            root->val+=d;
            Updata(root);
        }
        else{
            Read(l);
            Read(r);
            l++;r++;
            Splay(Ask(root,l-1),null);
            Splay(Ask(root,r+1),root);
            if(T==3){
                pf("%d\n",root->ch[1]->ch[0]->sum);
            }
            else if(T==4){
                pf("%d\n",root->ch[1]->ch[0]->max);
            }
            else{
                node* p=root->ch[1]->ch[0];
                p->lazy=!p->lazy;
                swap(p->ch[0],p->ch[1]);
            }
        }
    }
}

int main(){
    Init();
    Solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值