P2710 数列[fhq treap]

调了一辈子的fhq treap…

如果不会最大子段和

如果不会fhq treap

7个操作…
其中三个查询 单点查询其实可以和区间查询写成一个(

fhq treap 的修改操作大概就是 \(split\) 完了然后把修改区间的根 打上标记 等着下传就完事了…

那这题没了…我给个好一点的小数据…反正我照着这个调了挺久的…

.in
50 10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
GET 13
REVERSE 15 1
MAKE-SAME 1 1 3
REVERSE 21 8
GET-SUM 22 3
MAX-SUM 32 2
GET 8
DELETE 4 9
GET 36
REVERSE 34 2

.out
13
78
65
8
45
#include<cstdio>
#include<cstdlib>
#include<string>
#include<iostream>
int min(int x , int y) {
    return x < y ? x : y ;
}
int max(int x , int y) {
    return x > y ? x : y ;
}
void swap(int & x , int & y) {
    x ^= y ^= x ^= y ;
}

int read() {
    int x = 0 , f = 1 ;
    char c = getchar() ;
    while(c < 48 || c > 57) {
        if(c == '-') f = 0 ;
        c = getchar() ;
    }
    while(c >= 48 && c <= 57) {
        x = (x << 1) + (x << 3) + (c & 15) ;
        c = getchar() ;
    }
    return f ? x : -x ;
}

int n , m , rt , cnt ;
constexpr int N = 2e6 + 10 ;
constexpr int lim = 2333 ;
int a[N] ;
int rnd[N] , val[N] , sum[N] , sz[N] , ls[N] , rs[N] ;
int lmax[N] , rmax[N] , mx[N] ;
int tag[N] , rev[N] ;

void pushup(int o) {
    sz[o] = sz[ls[o]] + sz[rs[o]] + 1 ;
    sum[o] = sum[ls[o]] + sum[rs[o]] + val[o] ;
    lmax[o] = max(lmax[ls[o]] , sum[ls[o]] + max(0 , lmax[rs[o]]) + val[o]) ;
    rmax[o] = max(rmax[rs[o]] , sum[rs[o]] + max(0 , rmax[ls[o]]) + val[o]) ;
    mx[o] = max(0 , rmax[ls[o]]) + max(0 , lmax[rs[o]]) + val[o] ;
    if(ls[o]) mx[o] = max(mx[o] , mx[ls[o]]) ;
    if(rs[o]) mx[o] = max(mx[o] , mx[rs[o]]) ;
}

void reverse(int o) {
    swap(ls[o] , rs[o]) ;
    swap(lmax[o] , rmax[o]) ;
    rev[o] ^= 1 ;
}

void cover(int o , int v) {
    val[o] = tag[o] = v ;
    sum[o] = v * sz[o] ;
    lmax[o] = rmax[o] = mx[o] = max(sum[o] , v) ;
}

void pushdown(int o) {
    if(rev[o]) {
        if(ls[o]) reverse(ls[o]) ;
        if(rs[o]) reverse(rs[o]) ;
        rev[o] ^= 1 ;
    }
    if(tag[o] != lim) {
        if(ls[o]) cover(ls[o] , tag[o]) ;
        if(rs[o]) cover(rs[o] , tag[o]) ;
        tag[o] = lim ;
    }
}

int newnode(int k) {
    ++ cnt ;
    rnd[cnt] = rand() ;
    val[cnt] = sum[cnt] = k ;
    lmax[cnt] = rmax[cnt] = mx[cnt] = k ;
    sz[cnt] = 1 ;
    tag[cnt] = lim ;
    ls[cnt] = rs[cnt] = 0 ;
    return cnt ;
}

int merge(int x , int y) {
    if(! x || ! y) return x | y ;
    if(rnd[x] < rnd[y]) {
        pushdown(x) ;
        rs[x] = merge(rs[x] , y) ;
        pushup(x) ;
        return x ;
    } else {
        pushdown(y) ;
        ls[y] = merge(x , ls[y]) ;
        pushup(y) ;
        return y ;
    }
}

void split(int cur , int k , int & x , int & y) {
    if(! cur) {
        x = y = 0 ;
        return ;
    }
    pushdown(cur) ;
    if(sz[ls[cur]] < k) {
        split(rs[cur] , k - sz[ls[cur]] - 1 , x , y) ;
        rs[cur] = 0 ;
        pushup(cur) ;
        x = merge(cur , x) ;
    } else {
        split(ls[cur] , k , x , y) ;
        ls[cur] = 0 ;
        pushup(cur) ;
        y = merge(y , cur) ;
    }
}

int newrt(int len) {
    int _newrt = 0 ;
    for(int i = 1 ; i <= len ; i ++) _newrt = merge(_newrt , newnode(read())) ;
    return _newrt ;
}

void insert(int pos , int len) {
    int x , y ;
    split(rt , pos , x , y) ;
    rt = merge(merge(x , newrt(len)) , y) ;
}

void remove(int l , int r) {
    int x , y , z ;
    split(rt , l - 1 , x , z) ;
    split(z , r - l + 1 , y , z) ;
    rt = merge(x , z) ;
}

void rever(int l , int r) {
    int x , y , z ;
    split(rt , l - 1 , x , z) ;
    split(z , r - l + 1 , y , z) ;
    reverse(y) ;
    rt = merge(merge(x , y) , z) ;
}

void cover(int l , int r , int v) {
    int x , y , z ;
    split(rt , l - 1 , x , z) ;
    split(z , r - l + 1 , y , z) ;
    cover(y , v) ;
    rt = merge(merge(x , y) , z) ;
}

int query_sum(int l , int r) {
    int x , y , z ;
    split(rt , l - 1 , x , z) ;
    split(z , r - l + 1 , y , z) ;
    int res = sum[y] ;
    rt = merge(merge(x , y) , z) ;
    return res ;
}

int query_point(int pos) {
    int x , y , z ;
    split(rt , pos , x , z) ;
    split(x , pos - 1 , x , y) ;
    int res = val[y] ;
    rt = merge(merge(x , y) , z) ;
    return res ;
}

int query_max_sum(int l , int r) {
    int x , y , z ;
    split(rt , l - 1 , x , z) ;
    split(z , r - l + 1 , y , z) ;
    int res = mx[y] ;
    rt = merge(merge(x , y) , z) ;
    return res ;
}

int getopt(std :: string opt) {
    if(opt == "INSERT") return 1 ;
    if(opt == "DELETE") return 2 ;
    if(opt == "REVERSE") return 3 ;
    if(opt == "MAKE-SAME") return 4 ;
    if(opt == "GET-SUM") return 5 ;
    if(opt == "GET") return 6 ;
    if(opt == "MAX-SUM") return 7 ;
}

int main() {
    srand(19260817) ;
    n = read() , m = read() ;
    rt = newrt(n) ;
    while(m --) {
        std :: string s ;
        std :: cin >> s ;
        int opt = getopt(s) ;
        if(opt == 1) {
            int pos = read() , len = read() ;
            insert(pos , len) ;
        }
        if(opt == 2) {
            int pos = read() , len = read() ;
            remove(pos , pos + len - 1) ;
        }
        if(opt == 3) {
            int pos = read() , len = read() ;
            rever(pos , pos + len - 1) ;
        }
        if(opt == 4) {
            int pos = read() , len = read() , v = read() ;
            cover(pos , pos + len - 1 , v) ;
        }
        if(opt == 5) {
            int pos = read() , len = read() ;
            printf("%d\n" , query_sum(pos , pos + len - 1)) ;
        }
        if(opt == 6) printf("%d\n" , query_point(read())) ;
        if(opt == 7) {
            int pos = read() , len = read() ;
            printf("%d\n" , query_max_sum(pos , pos + len - 1)) ;
        }
    }
    return 0 ;
}

原文地址:https://www.cnblogs.com/Isaunoya/p/12005555.html

时间: 2024-08-30 06:57:11

P2710 数列[fhq treap]的相关文章

fhq treap

fhq-treap 小结 粗浅地学习了这个神奇的数据结构,下面瞎写一些感受 首先fhq treap是一个基于分裂与合并的平衡树,那么怎么分裂,怎么合并呢 我们分两种情况考虑 一.权值平衡树(我自己取的名字) 所谓权值平衡树,就是任何操作都只与权值有关的平衡树 比如最基础的分裂,合并操作 分裂就是把平衡树按照权值\(k\)分成两半,一边所有点的权值\(\leq k\),另一边权值\(\gt k\) 怎么分裂呢 首先根据\(treap\)的定义,所有点的权值是一颗二叉搜索树(BST),就是左边比他小

【bzoj1251】序列终结者——fhq treap

Description 给定一个长度为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种操作,给出正确的回答. Sampl

【POJ2761】【fhq treap】A Simple Problem with Integers

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In

FHQ Treap小结(神级数据结构!)

首先说一下, 这个东西可以搞一切bst,treap,splay所能搞的东西 pre 今天心血来潮, 想搞一搞平衡树, 先百度了一下平衡树,发现正宗的平衡树写法应该是在二叉查找树的基础上加什么左左左右右左右右的旋转之类的, 思路比较好理解,但是 代码量........ 一看就头大,, 然后,在洛谷翻题解的时候无意间看到了远航之曲发的一篇非常短小精悍的题解, 于是就学了一下 FHQ Treap 这个东西的学名应该是叫做fhq treap,应该是treap的强化版. 整个数据结构中只有两个操作: 1.

浅谈fhq treap

一.简介 fhq treap 与一般的treap主要有3点不同 1.不用旋转 2.以merge和split为核心操作,通过它们的组合实现平衡树的所有操作 3.可以可持久化 二.核心操作 代码中val表示节点权值,pri表示节点的优先级,维护小根堆 1.split 将1个treap分裂为两个treap 分裂主要有两种:以权值k作为分界点.以位置k作为分界点 ①以权值k作为分界点 设原来的treap根节点为root,分裂后的<=k的treap A 的根节点为x,>k的treap B 的根节点为y

平衡树合集(Treap,Splay,替罪羊,FHQ Treap)

今天翻了翻其他大佬的博客,发现自己有些...颓废... 有必要洗心革面,好好学习 序:正常的BST有可能退化,成为链,大大降低效率,所以有很多方法来保持左右size的平衡,本文将简单介绍Treap,Splay,替罪羊,FHQ Treap: 另:代码都是普通平衡树 1.Treap 树堆,在数据结构中也称Treap,是指有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树.其基本操作的期望时间复杂度为O(logn).相对于其他的平衡二叉搜索树,Treap的特点是实现简单,

洛谷P3391 【模板】文艺平衡树(Splay)(FHQ Treap)

题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n−1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)

简介: Treap,一种表现优异的BST 优势: 其较于AVL.红黑树实现简单,浅显易懂 较于Splay常数小,通常用于树套BST表现远远优于Splay 或许有人想说SBT,SBT我没有实现过,据说比较快 但是SBT.Splay以及旋转版Treap等BST都不可以比较方便地实现‘可持久化操作 Treap=Tree+Heap Treap是一颗同时拥有二叉搜索树和堆性质的一颗二叉树 Treap有两个关键字,在这里定义为: 1.key,满足二叉搜索树性质,即中序遍历按照key值有序 2.fix,满足堆

模板 - 数据结构 - 无旋Treap / FHQ Treap

普通平衡树: #include<bits/stdc++.h> using namespace std; typedef long long ll; #define ls(p) ch[p][0] #define rs(p) ch[p][1] const int MAXN = 100000 + 5; int val[MAXN], ch[MAXN][2], rnd[MAXN], siz[MAXN], tot, root; void Init() { tot = root = 0; } void Pu