您的位置:首页 > 其它

【bzoj1251】序列终结者 Splay

2015-12-08 21:59 337 查看

Description

网上有许多题,就是给定一个序列,要你支持几种操作: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

[code]4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4


Sample Output

[code]2


【数据范围】

N<=50000,M<=100000。

HINT

Source

Splay

加了点操作,多存点东西就可以了……pushdown多写点,函数大同小异…

代码:

[code]#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

const int SZ = 1000010;
const int INF = 1000000010;

struct node{
    node *ch[2],*f;
    int sz,cnt,v,maxn,add;
    bool flag;

    void maintain() 
    {
        sz = ch[0] -> sz + ch[1] -> sz + cnt;
        maxn = max(v,max(ch[0] -> maxn,ch[1] -> maxn));
    }   

    void setc(node *x,int d) { (ch[d] = x) -> f = this; }

    void pushdown();

    int dir() { return f -> ch[1] == this; }

}T[SZ], *root, *null;

int Tcnt = 0;

node* newnode(int x,node *fa)
{
    node *k = T + (Tcnt ++);

    k -> ch[1] = k -> ch[0] = null;
    k -> cnt = k -> sz = 1;
    k -> v = k -> maxn = x;
    k -> f = fa;
    k -> add = k -> flag = 0;
    return k;
}

void node::pushdown()
{
    if(flag)
    {
        flag = 0;
        if(ch[0] != null) ch[0] -> flag ^= 1;
        if(ch[1] != null) ch[1] -> flag ^= 1;
        swap(ch[0],ch[1]);
    }   
    if(add)
    {
        if(ch[0] != null) ch[0] -> add += add,ch[0] -> maxn += add,ch[0] -> v += add;
        if(ch[1] != null) ch[1] -> add += add,ch[1] -> maxn += add,ch[1] -> v += add;
        add = 0;
    }
}

void rotate(node *p)
{
    p -> f -> pushdown(); p -> pushdown();

    node *fa = p -> f;
    int d = p -> dir();
    fa -> f -> setc(p,fa -> dir()); 
    fa -> setc(p -> ch[d ^ 1],d); fa -> maintain();
    p -> setc(fa,d ^ 1); p -> maintain();
    if(fa == root) root = p;    
}

void splay(node *p,node *rt = null)
{
    while(p -> f != rt)
    {
        p -> pushdown();
        if(p -> f -> f == rt) rotate(p);
        else
        {
            if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p);
            else rotate(p),rotate(p); 
        } 
    }
}

node* find(node *p,int k)
{
    while(p != null)
    {
        p -> pushdown();
        int l = p -> ch[0] -> sz + 1;
        int r = p -> ch[0] -> sz + p -> cnt;
        if(l <= k && k <= r) return p;
        if(k > r) k -= r,p = p -> ch[1];
        else p = p -> ch[0];
    }
}

void change(node *p,int l,int r,int d)
{
    l ++; r ++;
    node *pre = find(root,l - 1);
    node *suf = find(root,r + 1);
    splay(pre); splay(suf,root);
    root -> ch[1] -> ch[0] -> add += d;
    root -> ch[1] -> ch[0] -> maxn += d;
    root -> ch[1] -> ch[0] -> v += d;
}

void reverse(node *p,int l,int r)
{
    l ++; r ++;
    node *pre = find(root,l - 1);
    node *suf = find(root,r + 1);
    splay(pre); splay(suf,root);
    root -> ch[1] -> ch[0] -> flag ^= 1;
}

int ask_max(node *p,int l,int r)
{
    l ++; r ++;
    node *pre = find(root,l - 1);
    node *suf = find(root,r + 1);
    splay(pre); splay(suf,root);
    return root -> ch[1] -> ch[0] -> maxn;
}

int n,m;

void build(node* &p,int l,int r,node *fa)
{
    if(l > r) return ;
    int mid = (l + r) >> 1;
    p = newnode(0,fa);
    build(p -> ch[0],l,mid - 1,p);
    build(p -> ch[1],mid + 1,r,p);
    p -> maintain();
}

void init()
{
    null = newnode(-INF,null);
    null -> sz = null -> cnt = 0;
    root = null;

    root = newnode(-INF,null);
    root -> ch[1] = newnode(INF,root);
    build(root -> ch[1] -> ch[0],1,n,root -> ch[1]);
    root -> ch[1] -> maintain();
    root -> maintain();
}

int main()
{
    scanf("%d%d",&n,&m);
    init();
    while(m --)
    {
        int k;
        scanf("%d",&k);
        int l,r,v;
        if(k == 1)
        {
            scanf("%d%d%d",&l,&r,&v);
            change(root,l,r,v);
        }
        else if(k == 2)
        {
            scanf("%d%d",&l,&r);
            reverse(root,l,r);
        }
        else
        {
            scanf("%d%d",&l,&r);
            printf("%d\n",ask_max(root,l,r));
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: