【bzoj3196】【坑】Tyvj 1730 二逼平衡树 线段树套Treap/Splay

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Input

第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

Output

对于操作1,2,4,5各输出一行,表示查询结果

Sample Input

9 6

4 2 2 1 9 4 0 1 1

2 1 4 3

3 4 10

2 1 4 3

1 2 5 9

4 3 9 5

5 2 8 5

Sample Output

2

4

3

4

9

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数

Source


不知道为什么,老是T

线段树维护treap或splay
我的代码真尼玛长,三百多行…………

先挖坑,以后再填

代码(Treap):

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;

const int SZ = 1000010;
const int INF = 100000010;


int num[SZ];
int n,m;
struct node{
    node *ch[2];
    int sz,v,cnt,r;

    int cmp(int x)
    {
        if(x == v) return -1;
        return x < v ? 0 : 1;
    }

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

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

}T[SZ],*null;

struct segnode{
    int l,r;
    node *root;
}tree[SZ * 4];

void dfs(node *p)
{
    if(p == null) return ;
    dfs(p -> ch[0]);
    printf("%d %d\n",p -> v,p -> cnt);
    dfs(p -> ch[1]);
}

int Tcnt = 0;

inline node* newnode(int x)
{
    node *k = T + (Tcnt ++);
    k -> ch[0] = k -> ch[1] = null;
    k -> v = x;
    k -> sz = k -> cnt = 1;
    k -> r = rand();
    return k;
}

inline void rotate(node* &p,int d)
{
    node *k = p -> ch[d ^ 1];
    p -> ch[d ^ 1] = k -> ch[d];
    k -> ch[d] = p;
    p -> maintain(); k -> maintain();
    p = k;
}

inline int treap_ask_rank(node *p,int x)
{
    int ans = 0;
    while(p != null)
    {
        int d = p -> cmp(x);
        if(d == -1) return ans + p -> ch[0] -> sz;
        if(d == 1) ans += p -> cnt + p -> ch[0] -> sz;
        p = p -> ch[d];
    }
    return ans;
}

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

inline void treap_insert(node* &p,int x)
{
    if(p == null)
    {
        p = newnode(x);
        return ;
    }

    int d = p -> cmp(x);
    if(d == -1)
    {
        p -> cnt ++;
        p -> sz ++;
        return ;
    }
    treap_insert(p -> ch[d],x);

    if(p -> ch[d] -> r < p -> r) rotate(p,d ^ 1);

    p -> maintain();
}

inline void treap_erase(node* &p,int x)
{
    if(p == null) return ;

    int d = p -> cmp(x);
    if(d == -1)
    {
        if(p -> cnt > 1)
        {
            p -> cnt --; p -> sz --; return ;
        }

        if(p -> ch[0] != null && p -> ch[1] != null)
        {
            int dd = p -> ch[0] -> r < p -> ch[1] -> r ? 0 : 1;
            rotate(p,dd ^ 1);
            treap_erase(p -> ch[dd ^ 1],x);
        }
        else
        {
            if(p -> ch[0] != null) p = p -> ch[0];
            else p = p -> ch[1];
        }
    }
    else
        treap_erase(p -> ch[d],x);
    if(p != null) p -> maintain();
}

inline void treap_change(node* &p,int x,int v)
{
    treap_erase(p,x);
/*  puts("erase");
    printf("%d %d %d\n",tree[pos].l,tree[pos].r,x);
    puts("dfs");dfs(tree[pos].root);puts("dfs\n");*/

    treap_insert(p,v);

/*  puts("insert");
    printf("%d %d %d\n",tree[pos].l,tree[pos].r,v);
    puts("dfs");dfs(tree[pos].root);puts("dfs\n");*/
}

inline int treap_ask_pre(node *p,int x)
{
    int ans = -INF;
    while(p != null)
    {
        if(p -> v < x) ans = p -> v,p = p -> ch[1];
        else p = p -> ch[0];
    }
    return ans;
}

inline int treap_ask_suf(node *p,int x)
{
    int ans = INF;
    while(p != null)
    {
        if(p -> v > x) ans = p -> v,p = p -> ch[0];
        else p = p -> ch[1];
    }
    return ans; 
}

inline void treap_build(int pos,int l,int r)
{
    for(register int i = l;i <= r;++ i) 
    {
        treap_insert(tree[pos].root,num[i]);
    }
}


inline void seg_build(int p,int l,int r)
{
    tree[p].l = l; tree[p].r = r;
    tree[p].root = null;
    treap_build(p,l,r);
    if(l == r)
    {
        return ;
    }
    int mid = (l + r) >> 1;
    seg_build(p << 1,l,mid);
    seg_build(p << 1 | 1,mid + 1,r);
}

inline int seg_ask_rank(int p,int l,int r,int x)
{
    if(l <= tree[p].l && tree[p].r <= r)
    {
        int ans = treap_ask_rank(tree[p].root,x);
    //  printf("%d %d %d\n",tree[p].l,tree[p].r,ans);
        return ans;
    }
    int mid = (tree[p].l + tree[p].r) >> 1;
    int ans = 0;
    if(l <= mid) ans += seg_ask_rank(p << 1,l,r,x);
    if(mid < r) ans += seg_ask_rank(p << 1 | 1,l,r,x);
    return ans;
}


inline int seg_ask_num(int p,int l,int r,int k)
{
    int ll = 0,rr = INF,ans;
    while(ll <= rr)
    {
        int mid = (ll + rr) >> 1;
        int tmp = seg_ask_rank(1,l,r,mid) + 1;
        if(tmp <= k) ll = mid + 1,ans = mid;
        else rr = mid - 1;
    }
    return ans;
}

inline void seg_change(int p,int pos,int x)
{
    treap_change(tree[p].root,num[pos],x);
    if(tree[p].l == tree[p].r) return ;
    int mid = (tree[p].l + tree[p].r) >> 1; 
    if(pos <= mid) seg_change(p << 1,pos,x);
    else seg_change(p << 1 | 1,pos,x);
}

inline int seg_ask_pre(int p,int l,int r,int x)
{
    if(l <= tree[p].l && tree[p].r <= r)
    {
        int ans = treap_ask_pre(tree[p].root,x);
//      printf("hahaha %d %d %d %d\n",ans,x,l,r); 
        return ans;
    }
    int ans = -INF;
    int mid = (tree[p].l + tree[p].r) >> 1;
    if(l <= mid) ans = max(ans,seg_ask_pre(p << 1,l,r,x));
    if(mid < r) ans = max(ans,seg_ask_pre(p << 1 | 1,l,r,x));
    return ans;
}

inline int seg_ask_suf(int p,int l,int r,int x)
{
    if(l <= tree[p].l && tree[p].r <= r)
        return treap_ask_suf(tree[p].root,x);
    int ans = INF;
    int mid = (tree[p].l + tree[p].r) >> 1;
    if(l <= mid) ans = min(ans,seg_ask_suf(p << 1,l,r,x));
    if(mid < r) ans = min(ans,seg_ask_suf(p << 1 | 1,l,r,x));
    return ans;
}

inline void init()
{
    null = newnode(-INF);
    null -> sz = null -> cnt = 0;
    null -> r = -INF;
    srand(time(0));
}

inline void scan(int &n)
{
    n = 0;
    char a = getchar();
    bool flag = 0;
    while(a < '0' || a > '9') {if(a == '-') flag = 1; a = getchar();}
    while('0' <= a && a <= '9') n = (n << 3) + (n << 1) + a - '0',a = getchar();
    if(flag) n = -n;
}

int main()
{
//  freopen("3196.in","r",stdin);       freopen("3196.out","w",stdout);     
    init();
    scan(n),scan(m);
    for(int i = 1;i <= n;++ i) scan(num[i]);
    seg_build(1,1,n);
    while(m --)
    {
        int opt;
        scan(opt);
        int l,r,k,pos;
        switch(opt)
        {
            case 1:
                scan(l); scan(r); scan(k);
                printf("%d\n",seg_ask_rank(1,l,r,k) + 1);
                break;
            case 2:
                scan(l); scan(r); scan(k);
                printf("%d\n",seg_ask_num(1,l,r,k));
                break;
            case 3:
                scan(pos); scan(k);
                seg_change(1,pos,k);
                num[pos] = k;
                break;
            case 4:
                scan(l); scan(r); scan(k);
                printf("%d\n",seg_ask_pre(1,l,r,k));
                break;
            case 5:
                scan(l); scan(r); scan(k);
                printf("%d\n",seg_ask_suf(1,l,r,k));
                break;
        }
    //  dfs(tree[1].root); puts("");
    }
    return 0;
}
/*
3 9
9 3 6 
3 3 9


5 10 1 10 3 1 8 


*/

Splay:

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

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


int num[SZ];
int n,m;
struct node{
    node *f,*ch[2];
    int sz,v,cnt;

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

    int cmp(int x)
    {
        if(x == v) return -1;
        return x < v ? 0 : 1;
    }

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

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

}T[SZ],*null;

struct segnode{
    int l,r;
    node *root;
    int sum;
}tree[SZ * 4];

void dfs(node *p)
{
    if(p == null) return ;
    dfs(p -> ch[0]);
    printf("%d %d\n",p -> v,p -> cnt);
    dfs(p -> ch[1]);
}

int Tcnt = 0;

node* newnode(int x,node *fa)
{
    node *k = T + (Tcnt ++);
    k -> f = fa;
    k -> ch[0] = k -> ch[1] = null;
    k -> v = x;
    k -> sz = k -> cnt = 1;
    return k;
}

void rotate(int pos,node *p)
{
    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 == tree[pos].root) tree[pos].root = p;
}

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

int splay_ask_rank(node *p,int x)
{
    int ans = 0;
    while(p != null)
    {
        int d = p -> cmp(x);
        if(d == -1) return ans + p -> ch[0] -> sz;
        if(d == 1) ans += p -> cnt + p -> ch[0] -> sz;
        p = p -> ch[d];
    }
    return ans;
}

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

void splay_erase(int pos,node *p,int x)
{
    while(p != null)
    {
        p -> sz --;
        int d = p -> cmp(x);
        if(d == -1) { p -> cnt --; break; }
        p = p -> ch[d];
    }
    if(p -> cnt) return ;
    splay(pos,p);
    if(p -> ch[0] == null) { tree[pos].root = p -> ch[1]; tree[pos].root -> f = null; return ; }
    if(p -> ch[1] == null) { tree[pos].root = p -> ch[0]; tree[pos].root -> f = null; return ; }
    p = p -> ch[0];
    while(p -> ch[1] != null) p = p -> ch[1];
    splay(pos,p,tree[pos].root);
    p -> ch[1] = tree[pos].root -> ch[1]; p -> ch[1] -> f = p;
    p -> f = null; p -> maintain();
    tree[pos].root = p;
}

void splay_insert(int pos,node *p,int x)
{
    if(tree[pos].root == null) { tree[pos].root = newnode(x,null); return ; }
//  printf("rt : %d \n",tree[pos].root -> v);
    while(p != null)
    {
        p -> sz ++;
        int d = p -> cmp(x);
        if(d == -1) { p -> cnt ++;break; }
//      printf("I : %d %d\n",p -> v,d);
        if(p -> ch[d] == null)
        {
            p -> ch[d] = newnode(x,p);
            p = p -> ch[d];
            break;
        }
        p = p -> ch[d];
    }
    splay(pos,p);
}

void splay_change(int pos,node *p,int x,int v)
{
    splay_erase(pos,tree[pos].root,x);
//  puts("erase");
//  printf("%d %d %d\n",tree[pos].l,tree[pos].r,x);
//  puts("dfs");dfs(tree[pos].root);puts("dfs\n");

    splay_insert(pos,tree[pos].root,v);

//  puts("insert");
//  printf("%d %d %d\n",tree[pos].l,tree[pos].r,v);
//  puts("dfs");dfs(tree[pos].root);puts("dfs\n");
}

int splay_ask_pre(node *p,int x)
{
    int ans = -INF;
    while(p != null)
    {
        if(p -> v < x) ans = p -> v,p = p -> ch[1];
        else p = p -> ch[0];
    }
    return ans;
}

int splay_ask_suf(node *p,int x)
{
    int ans = INF;
    while(p != null)
    {
        if(p -> v > x) ans = p -> v,p = p -> ch[0];
        else p = p -> ch[1];
    }
    return ans; 
}

void splay_build(int pos,int l,int r)
{
    for(int i = l;i <= r;i ++) 
    {
        splay_insert(pos,tree[pos].root,num[i]);
    }
}


void seg_update(int p)
{
    tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
}

void seg_build(int p,int l,int r)
{
    tree[p].l = l; tree[p].r = r;
    tree[p].root = null;
    splay_build(p,l,r);
    if(l == r)
    {
        tree[p].sum = num[l];
        return ;
    }
    int mid = (l + r) >> 1;
    seg_build(p << 1,l,mid);
    seg_build(p << 1 | 1,mid + 1,r);
    seg_update(p);
}

int seg_ask_rank(int p,int l,int r,int x)
{
    if(l <= tree[p].l && tree[p].r <= r)
    {
        int ans = splay_ask_rank(tree[p].root,x);
    //  printf("%d %d %d\n",tree[p].l,tree[p].r,ans);
        return ans;
    }
    int mid = (tree[p].l + tree[p].r) >> 1;
    int ans = 0;
    if(l <= mid) ans += seg_ask_rank(p << 1,l,r,x);
    if(mid < r) ans += seg_ask_rank(p << 1 | 1,l,r,x);
    return ans;
}


int seg_ask_num(int p,int l,int r,int k)
{
    int ll = 0,rr = INF,ans;
    while(ll <= rr)
    {
        int mid = (ll + rr) >> 1;
        int tmp = seg_ask_rank(1,l,r,mid) + 1;
        if(tmp <= k) ll = mid + 1,ans = mid;
        else rr = mid - 1;
    }
    return ans;
}

void seg_change(int p,int pos,int x)
{
    splay_change(p,tree[p].root,num[pos],x);
    if(tree[p].l == tree[p].r) return ;
    int mid = (tree[p].l + tree[p].r) >> 1; 
    if(pos <= mid) seg_change(p << 1,pos,x);
    if(mid < pos) seg_change(p << 1 | 1,pos,x);
    seg_update(p);
}

int seg_ask_pre(int p,int l,int r,int x)
{
    if(l <= tree[p].l && tree[p].r <= r)
    {
        int ans = splay_ask_pre(tree[p].root,x);
//      printf("hahaha %d %d %d %d\n",ans,x,l,r); 
        return ans;
    }
    int ans = -INF;
    int mid = (tree[p].l + tree[p].r) >> 1;
    if(l <= mid) ans = max(ans,seg_ask_pre(p << 1,l,r,x));
    if(mid < r) ans = max(ans,seg_ask_pre(p << 1 | 1,l,r,x));
    return ans;
}

int seg_ask_suf(int p,int l,int r,int x)
{
    if(l <= tree[p].l && tree[p].r <= r)
        return splay_ask_suf(tree[p].root,x);
    int ans = INF;
    int mid = (tree[p].l + tree[p].r) >> 1;
    if(l <= mid) ans = min(ans,seg_ask_suf(p << 1,l,r,x));
    if(mid < r) ans = min(ans,seg_ask_suf(p << 1 | 1,l,r,x));
    return ans;
}

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

void scan(int &n)
{
    n = 0;
    char a = getchar();
    bool flag = 0;
    while(a < '0' || a > '9') {if(a == '-') flag = 1; a = getchar();}
    while('0' <= a && a <= '9') n = (n << 3) + (n << 1) + a - '0',a = getchar();
    if(flag) n = -n;
}

int main()
{
//  freopen("3196.in","r",stdin);       freopen("3196.out","w",stdout);     
    init();
    scan(n),scan(m);
    for(int i = 1;i <= n;++ i) scan(num[i]);
    seg_build(1,1,n);
    while(m --)
    {
        int opt;
        scan(opt);
        int l,r,k,pos;
        switch(opt)
        {
            case 1:
                scan(l); scan(r); scan(k);
                printf("%d\n",seg_ask_rank(1,l,r,k) + 1);
                break;
            case 2:
                scan(l); scan(r); scan(k);
                printf("%d\n",seg_ask_num(1,l,r,k));
                break;
            case 3:
                scan(pos); scan(k);
                seg_change(1,pos,k);
                num[pos] = k;
                break;
            case 4:
                scan(l); scan(r); scan(k);
                printf("%d\n",seg_ask_pre(1,l,r,k));
                break;
            case 5:
                scan(l); scan(r); scan(k);
                printf("%d\n",seg_ask_suf(1,l,r,k));
                break;
        }
//      dfs(tree[1].root); puts("");
    }
    return 0;
}
/*
4 2 2 10 9 4 0 1 1
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值