BZOJ 3196: Tyvj 1730 二逼平衡树 窒息的操作

来源:互联网 发布:量化分析 java python 编辑:程序博客网 时间:2024/05/17 03:30

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3196
题意:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
思路:窒息的操作
code:

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int mod = 1e9 + 7;const int maxn = 5e4 + 1000;inline void read(int &x){x = 0;char p = getchar();while(!(p <= '9' && p >= '0'))p = getchar();while(p <= '9' && p >= '0')x *= 10, x += p - 48, p = getchar();}int d[maxn], m, n, p, s, t, v;typedef vector<int>vec;vec a[maxn];inline void ins(vec&a, int v){ a.insert(lower_bound(a.begin(), a.end(), v), v);}inline void del(vec&a, int v){ a.erase(lower_bound(a.begin(), a.end(), v));}inline void ins(int i, int v){ for(; i <= n; i += i & -i) ins(a[i], v);}inline void del(int i, int v){ for(; i <= n; i += i & -i)del(a[i], v);}inline int ask(vec&a, int v) {return lower_bound(a.begin(), a.end(), v) - a.begin();}inline int ask(int v, int s, int t){    int k = 1;    for(; s; s ^= s & -s)k -= ask(a[s], v);    for(; t; t ^= t & -t)k += ask(a[t], v);    return k;}inline int cal(int v, int s, int t){    int l = 0, r = 1e8;    while(l ^ r)    {        int j = l + r + 1 >> 1;        v >= ask(j, s, t) ? l = j : r = j - 1;    }    return l;}int main(){    scanf("%d%d", &n, &m);    for(int i = 1; i <= n; ++i) read(d[i]);    for(int i = 1; i <= n; ++i) ins(i, d[i]);    for(int i=1;i<=m;i++)    {        scanf("%d%d%d", &p, &s, &t);        if(p == 3)        {            del(s, d[s]), ins(s, d[s] = t);///修改某一位置上的数值;            continue;        }        int ans=0;        --s, scanf("%d", &v);        if(p == 1) ans=ask(v, s, t);///查询 x在区间内的排名;        if(p == 2) ans=cal(v, s, t);///查询区间内排名为 k 的值;         ///查询 x x x 在区间内的前趋(前趋定义为小于 x,且最大的数);        if(p == 5) ans=cal(ask(v + 1, s, t), s, t);        ///查询 x x x 在区间内的后继(后继定义为大于 x,且最小的数)。        printf("%d\n",ans);    }    return 0;}
原创粉丝点击