HYSBZ 3196 Tyvj 1730 二逼平衡树(树套树)

bzoj能过.tyvj有两组TLE了.以后写分块看能不能过

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

#define LL long long 
#define pii pair<int, int>
#define MP make_pair
#define ls i << 1
#define rs ls | 1
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 50010
#define M 400020

char buf[16000000],*pt = buf,*o = buf;
int getint(){
    int f = 1,x = 0;
    while((*pt != '-') && (*pt < '0' || *pt > '9'))    pt ++;
    if(*pt == '-')    f = -1,pt ++;    else    x = *pt++ - 48;
    while(*pt >= '0' && *pt <= '9')    x = x * 10 + *pt ++ - 48;
    return x * f;
}
char getch(){
    char ch;
    while(*pt < 'A' || *pt > 'Z')    pt ++;
    ch=*pt;pt++;
    return ch;
}
int ch[N*30][2];  
int rand_val[N*30], key[N*30], sz[N*30], cnt[N*30];  
int tot, rt[N<<2], a[N];
int creat(int val) {  
    ++tot;  
    ch[tot][0] = ch[tot][1] = 0;  
    rand_val[tot] = rand();  
    key[tot] = val;  
    sz[tot] = cnt[tot] = 1;  
    return tot;  
}
int cmp(int x, int val) {  
    if(key[x] == val) return -1;  
    return val < key[x]? 0: 1;  
}
void push_up(int x) {  
    sz[x] = cnt[x] + sz[ch[x][0]] + sz[ch[x][1]];  
}  
void rot(int &x, int d) {  
    int k = ch[x][d^1];  
    ch[x][d^1] = ch[k][d];  
    ch[k][d] = x;  
    push_up(x);  
    push_up(k);  
    x = k;  
}  
void insert(int &x, int val) {  
    if(x == 0) {  
        x = creat(val);  
        return;  
    }  
    int d = cmp(x, val);  
    if(d == -1) {  
        cnt[x]++, sz[x]++;  
        return;  
    }  
    insert(ch[x][d], val);  
    if(rand_val[ch[x][d]] > rand_val[x]) rot(x, d ^ 1);  
    push_up(x);  
}  
void del(int &x, int val) {  
    if(x == 0) return;  
    int d = cmp(x, val);  
    if(d == -1) {  
        if(cnt[x] > 1) {  
            cnt[x]--, sz[x]--;  
            return;  
        }  
        if(!ch[x][0]) x = ch[x][1];  
        else if(!ch[x][1]) x = ch[x][0];  
        else {  
            int d2 = rand_val[ch[x][0]] > rand_val[ch[x][1]]? 1: 0;  
            rot(x, d2);  
            del(ch[x][d2], val);  
        }  
    }  
    else del(ch[x][d], val);  
    if(x) push_up(x);  
} 
int kth(int x, int val){
    if(!x) return 0;
    int d = cmp(x, val);
    if(d == -1)
        return sz[ch[x][0]] + cnt[x];
    if(d == 0)
        return kth(ch[x][0], val);
    return sz[ch[x][0]] + cnt[x] + kth(ch[x][1], val);
}
int find_pre(int x, int val){
    if(!x) return -inf;
    int d = cmp(x, val);
    if(d == 1)
        return max(key[x], find_pre(ch[x][1], val));
    return find_pre(ch[x][0], val);
}
int find_suf(int x, int val){
    if(!x) return inf;
    int d = cmp(x, val);
    if(d == 0)
        return min(key[x], find_suf(ch[x][0], val));
    return find_suf(ch[x][1], val);
}

void build(int ll, int rr, int i){
    rt[i] = 0;
    for(int j = ll; j <= rr; ++j)
        insert(rt[i], a[j]);
    if(ll == rr) return ;
    build(lson);
    build(rson);
}
void update(int x, int pre, int cur, int ll, int rr, int i){
    del(rt[i], pre);
    insert(rt[i], cur);
    if(ll == rr) return ;
    if(x <= md) update(x, pre, cur, lson);
    else update(x, pre, cur, rson);
}
int query_1(int l, int r, int v, int ll, int rr, int i){
    if(l <= ll && r >= rr)
        return kth(rt[i], v);
    if(r <= md) return query_1(l, r, v, lson);
    else if(l > md) return query_1(l, r, v, rson);
    else return query_1(l, md, v, lson) + query_1(md + 1, r, v, rson);
}
int query_4(int l, int r, int v, int ll, int rr, int i){
    if(l <= ll && r >= rr)
        return find_pre(rt[i], v);
    if(r <= md) return query_4(l, r, v, lson);
    else if(l > md) return query_4(l, r, v, rson);
    else return max(query_4(l, md, v, lson), query_4(md + 1, r, v, rson));
}
int query_5(int l, int r, int v, int ll, int rr, int i){
    if(l <= ll && r >= rr)
        return find_suf(rt[i], v);
    if(r <= md) return query_5(l, r, v, lson);
    else if(l > md) return query_5(l, r, v, rson);
    else return min(query_5(l, md, v, lson), query_5(md + 1, r, v, rson));
}
int main(){
    //freopen("tt.txt", "r", stdin);
    fread(buf, 1, 16000000, stdin);
    int n, m;
    n = getint(), m = getint();
    for(int i = 1; i <= n; ++i)
        a[i] = getint();
    tot = 0;
    build(1, n, 1);
    while(m--){
        int op, l, r, k;
        op = getint();
        if(op == 3){
            l = getint(), k = getint();
            update(l, a[l], k, 1, n, 1);
            a[l] = k;
            continue;
        }
        l = getint(), r = getint(), k = getint();
        if(op == 1)
            printf("%d\n", query_1(l, r, k - 1, 1, n, 1) + 1);
        else if(op == 2){
            int L = 0, R = inf;
            while(L < R){
                int mid = (L + R) >> 1;
                if(query_1(l, r, mid, 1, n, 1) >= k)
                    R = mid;
                else L = mid + 1;
            }
            printf("%d\n", L);
        }
        else if(op == 4)
            printf("%d\n", query_4(l, r, k, 1, n, 1));
        else printf("%d\n", query_5(l, r, k, 1, n, 1));
    }       
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值