【模板】二逼平衡树(树套树)【树状数组套线段树】

26人阅读 评论(0) 收藏 举报
分类:

题目描述

被各种毒瘤线段树虐过后突然感觉这道卡了我一万年的树套树很水
(就一道模板题,不想讲了)
代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
const int N=50010, inf=2147483647;
int n, m, a[N], b[N<<1], cnt;
int rt[N], idx, ch[N<<8][2], sz[N<<8], xx[N], yy[N], totx, toty;
#define ls(o) ch[o][1]
#define rs(o) ch[o][2]

void ins(int &o, int x, int v, int l=1, int r=cnt){
    if(!o) o=++idx; sz[o]+=v; if(l == r) return ; int mid=l+r>>1; 
    if(x <= mid) ins(ls(o), x, v, l, mid); else ins(rs(o), x, v, mid+1, r);
} 
void modify(int x, int v){
    int k=lower_bound(b+1, b+cnt+1, a[x])-b;
    for(int i=x; i <= n; i+=i&(-i)) ins(rt[i], k, v);
}

void getsum(int &sum){for(int i=1; i <= totx; i++) sum-=sz[ls(xx[i])]; for(int i=1; i <= toty; i++) sum+=sz[ls(yy[i])];}
void getls(){for(int i=1; i <= totx; i++) xx[i]=ls(xx[i]); for(int i=1; i <= toty; i++) yy[i]=ls(yy[i]);}
void getrs(){for(int i=1; i <= totx; i++) xx[i]=rs(xx[i]); for(int i=1; i <= toty; i++) yy[i]=rs(yy[i]);}
void prepare(int L, int R){for(int i=L-1; i; i-=i&-i) xx[++totx]=rt[i]; for(int i=R; i; i-=i&-i) yy[++toty]=rt[i];}
int find_kth(int k, int l=1, int r=cnt){
    if(l == r) return l; int mid=l+r>>1, ss=0; getsum(ss);
    if(ss >= k) {getls(); return find_kth(k, l, mid);}
    getrs(); return find_kth(k-ss, mid+1, r);
}
void Find_kth(int L, int R, int K){totx=toty=0; prepare(L, R); printf("%d\n", b[find_kth(K)]);}

int get_rank(int o, int x, int l=1, int r=cnt){
    if(!o) return 0; if(l == r) {if(x == l) return 0; return sz[o];} int mid=l+r>>1;
    if(x <= mid) return get_rank(ls(o), x, l, mid); return sz[ls(o)]+get_rank(rs(o), x, mid+1, r);
}
void Get_rank(int L, int R, int c){
    int ss=0, x=lower_bound(b+1, b+1+cnt, c)-b;
    for(int i=L-1; i; i-=i&-i) ss-=get_rank(rt[i], x);
    for(int i=R; i; i-=i&-i) ss+=get_rank(rt[i], x);
    printf("%d\n", ss+1);
}

void Get_pre(int L, int R, int c){
    int ss=0, x=lower_bound(b+1, b+1+cnt, c)-b;
    for(int i=L-1; i; i-=i&-i) ss-=get_rank(rt[i], x);
    for(int i=R; i; i-=i&-i) ss+=get_rank(rt[i], x);
    if(!ss) printf("%d\n", -inf);
    else Find_kth(L, R, ss);
}
void Get_post(int L, int R, int c){
    int ss=0, x=lower_bound(b+1, b+1+cnt, c)-b+1;
    for(int i=L-1; i; i-=i&-i) ss-=get_rank(rt[i], x);
    for(int i=R; i; i-=i&-i) ss+=get_rank(rt[i], x);
    if(ss > R-L) printf("%d\n", inf);
    else Find_kth(L, R, ss+1);
}

int read(){
    int out=0, f=1; char c=getchar(); 
    while(c < '0' || c > '9') {if(c == '-') f=-1; c=getchar();}
    while(c >= '0' && c <= '9') {out=(out<<1)+(out<<3)+c-'0'; c=getchar();}
    return out*f;
}

int cmd[N], ql[N], qr[N], qk[N];
void solve()
{
    n=read(); m=read();  
    for(int i=1; i <= n; i++) a[i]=read(), b[++cnt]=a[i];
    for(int i=1; i <= m; i++) {
        cmd[i]=read(), ql[i]=read(), qr[i]=read(); 
        if(cmd[i] != 3) qk[i]=read(); 
        if(cmd[i] == 3) b[++cnt]=qr[i];
        else if(cmd[i] != 2) b[++cnt]=qk[i]; 
    }
    sort(b+1, b+cnt+1); cnt=unique(b+1, b+cnt+1)-b-1;
    for(int i=1; i <= n; i++) modify(i, 1);
    for(int i=1; i <= m; i++){
        if(cmd[i] == 1) Get_rank(ql[i], qr[i], qk[i]);
        if(cmd[i] == 2) Find_kth(ql[i], qr[i], qk[i]);
        if(cmd[i] == 3) modify(ql[i], -1), a[ql[i]]=qr[i], modify(ql[i], 1);
        if(cmd[i] == 4) Get_pre(ql[i], qr[i], qk[i]);
        if(cmd[i] == 5) Get_post(ql[i], qr[i], qk[i]);
    }
}

int main()
{
    solve();
    return 0;
}
查看评论

数据结构基础系列(6):树和二叉树

-
  • 1970年01月01日 08:00

BZOJ 3196: Tyvj 1730 二逼平衡树|线段树套平衡树

第一次写真正的树套树:线段树套平衡树?!(平衡树套线段树?!) 线段树维护的是区间,然后对于线段树维护的区间的所有数字都维护一个平衡树,然后所有的操作都对每个平衡树单独处理。 比如说操作3,需要先...
  • ws_yzy
  • ws_yzy
  • 2016-02-23 15:18:09
  • 693

BZOJ 3196 二逼平衡树 树套树(线段树套Treap)

题目大意: 写一种数据结构,他可以: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱定义为小于x,且最大的数) 5.查询k在区间内的后继...
  • jiangyuze831
  • jiangyuze831
  • 2014-09-23 16:51:02
  • 910

3196: Tyvj 1730 二逼平衡树 线段树套平衡树

看了看上次刷题时间是2.4真是感人。。似乎从WC回来后就一直在颓废。。 假期的最后一天决定刷几个题收收心。。清早来一发数据结构压压惊。。 线段树套平衡树裸题啦。。 一定是我的姿势不对好慢啊qwq...
  • Phenix_2015
  • Phenix_2015
  • 2016-02-13 09:25:08
  • 619

二逼平衡树(树套树)

树套树编程技巧。 1.tmp,这个答案的中间变量,便于解题。 2.用splay结构体来写树套树。   #include #include #include #include #incl...
  • zhhx2001
  • zhhx2001
  • 2016-09-07 20:09:05
  • 359

区间第k大 可修改主席树,树状数组套线段树。

#include #include using namespace std;const int N = 100010;struct Node { int cnt; Node *ls...
  • Kamisama123
  • Kamisama123
  • 2017-06-02 20:43:49
  • 304

bzoj 1901 ZOJ 2112 Dynamic Rankings [树状数组套主席树] [线段树套平衡树]

Dynamic RankingsTime Limit: 10 Sec Memory Limit: 128 MB Submit: 6900 Solved: 2870Description给定一个含...
  • ourfutr2330
  • ourfutr2330
  • 2016-08-06 15:39:29
  • 598

【bzoj3196】【二逼平衡树】【线段树套平衡树】

Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k...
  • sunshinezff
  • sunshinezff
  • 2016-06-09 17:02:13
  • 244

洛谷P3380:二逼平衡树 (树套树)

题目传送门:https://www.luogu.org/problemnew/show/3380题目分析:为什么我要把这道模板题写在博客上呢?因为我想记录一个卡常的小技巧。骗访问量这题我是考noip之...
  • KsCla
  • KsCla
  • 2017-11-16 21:38:45
  • 232

[BZOJ3196]二逼平衡树(线段树套splay)

花费了不知多少页来描述我们的心情 却不知为何填不满一行的空白
  • Clove_unique
  • Clove_unique
  • 2016-04-29 09:59:08
  • 1988
    个人资料
    持之以恒
    等级:
    访问量: 1992
    积分: 301
    排名: 25万+