[BZOJ3196]Tyvj 1730 二逼平衡树

来源:互联网 发布:缤纷童年吧事件知乎 编辑:程序博客网 时间:2024/05/17 08:25

Tyvj 1730 二逼平衡树

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可能为负数

Solution
就是动态区间第k大多一点查询

Code

#include <bits/stdc++.h>using namespace std;#define rep(i, l, r) for (int i = (l); i <= (r); i++)#define per(i, r, l) for (int i = (r); i >= (l); i--)#define MS(_) memset(_, 0, sizeof(_))#define PB push_back#define MP make_pair#define debug(...) fprintf(stderr, __VA_ARGS__)template<typename T> inline void read(T &x){    x = 0; T f = 1; char ch = getchar();    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}    while (isdigit(ch))  {x = x * 10 + ch - '0'; ch = getchar();}    x *= f;}const int INF = 1e8+1;const int N = 50000+10;struct Node{    int sum; Node *lc, *rc;}pool[N*200], *tail=pool+1, *null=pool, *root[N];int n, m, a[N], lcnt, rcnt;Node *lrt[16*2], *rrt[16*2];#define GETROOT\    lcnt = 0; for (int x = l-1; x>0; x-=lowbit(x)) lrt[++lcnt] = root[x];\    rcnt = 0; for (int x = r; x>0; x-=lowbit(x)) rrt[++rcnt] = root[x];inline int lowbit(int x) { return x&-x; }inline void setnull(){ null->lc = null->rc = null; }inline Node *newNode() { tail->lc = tail->rc = null; return tail++; }inline void mdf(Node *&rt, int l, int r, int p, int dt){    if (rt == null) rt = newNode();    rt->sum += dt;    if (l == r) return;    int mid = l+r >> 1;    if (p <= mid) mdf(rt->lc, l, mid, p, dt);    else mdf(rt->rc, mid+1, r, p, dt);}inline void modify(int x, int p, int dt){    for(; x <= n; x += lowbit(x)) mdf(root[x], 1, INF, p, dt);}inline int QrySum(int l, int r, int p){     int sum = 0;    if (l == r){        rep(i, 1, lcnt) sum -= lrt[i]->sum;        rep(i, 1, rcnt) sum += rrt[i]->sum;        return sum;    }else{        int mid = l+r >> 1;        if (p > mid){            rep(i, 1, lcnt) sum -= lrt[i]->lc->sum, lrt[i] = lrt[i]->rc;            rep(i, 1, rcnt) sum += rrt[i]->lc->sum, rrt[i] = rrt[i]->rc;            return sum+QrySum(mid+1, r, p);        }else{            rep(i, 1, lcnt) lrt[i] = lrt[i]->lc;            rep(i, 1, rcnt) rrt[i] = rrt[i]->lc;            return QrySum(l, mid, p);        }    }}inline int QryKth(int l, int r, int p){    if (l == r) return l-1;    int sum = 0, mid = l+r >> 1;    rep(i, 1, lcnt) sum -= lrt[i]->lc->sum;    rep(i, 1, rcnt) sum += rrt[i]->lc->sum;    if (p <= sum){        rep(i, 1, lcnt) lrt[i] = lrt[i]->lc;        rep(i, 1, rcnt) rrt[i] = rrt[i]->lc;        return QryKth(l, mid, p);    }else{        rep(i, 1, lcnt) lrt[i] = lrt[i]->rc;        rep(i, 1, rcnt) rrt[i] = rrt[i]->rc;        return QryKth(mid+1, r, p-sum);    }}inline int qryRank(int l, int r, int k){    GETROOT    return 1+(k ? QrySum(1, INF, k) : 0);}inline int qryKth(int l, int r, int k){    GETROOT    return QryKth(1, INF, k);}inline int qryPre(int l, int r, int k){    k = k > INF ? INF : k;    GETROOT    int rank = QrySum(1, INF, k);    GETROOT    return QryKth(1, INF, rank);    }inline int qryNxt(int l, int r, int k){    GETROOT    int rank = 1 + (k>=0 ? QrySum(1, INF, k+1) : 0);    GETROOT    return QryKth(1, INF, rank);}int main(){    read(n); read(m);    rep(i, 1, n) read(a[i]), a[i]++;    setnull();    rep(i, 1, n) root[i] = null;    rep(i, 1, n) modify(i, a[i], 1);    while (m--){ int opt, l, r, k;        read(opt); read(l); read(r);        if (opt == 3) modify(l, a[l], -1), modify(l, a[l]=r+1, 1);        else{            read(k);            if (opt == 1) printf("%d\n", qryRank(l, r, k));            else if (opt == 2) printf("%d\n", qryKth(l, r, k));            else if (opt == 4) printf("%d\n", qryPre(l, r, k));            else if (opt == 5) printf("%d\n", qryNxt(l, r, k));        }    }    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 神笔添加视频尺码不符合怎么办 闲鱼卖家单号填错了怎么办 户户通没有信号强度怎么办 全民k歌qq登不上怎么办 手机直播没电了怎么办 淘宝退货卖家拒收怎么办 充的会员卡店家关门了怎么办 淘宝手机号码被注册了怎么办 淘宝不支持七天无理由退货怎么办 微信视频横屏怎么办 房子里潮气太重怎么办 淘宝不小心注销了怎么办 淘宝号不小心注销了怎么办 xp网络驱动没了怎么办 淘宝卖家客服态度差怎么办 怀孕吃辣椒喉咙好痛怎么办 淘宝店铺建议不要提交认证怎么办 淘宝买东西商家不退款怎么办 淘宝买东西商家不发货怎么办 在微信上买东西被骗了怎么办 新浪微博自动关注人怎么办 搜淘宝找不到关键词和店铺怎么办 小超市开在一起竞争太大怎么办 淘宝店铺被投诉盗图怎么办 充电宝ic坏了怎么办 淘宝店宝贝权重下降怎么办 淘宝卖家评分低怎么办 淘宝买东西客服不理人怎么办 支付宝本次交易嫌疑违规怎么办 支付宝一年的交易总额怎么办 交易关闭钱扣了怎么办 交易猫账号绑定支付宝打不开怎么办 拼多多涉假处罚怎么办 淘宝店铺重复铺货扣6分怎么办 帆布鞋子买大了怎么办 开淘宝店没销量怎么办 开淘宝店没有销量怎么办 淘宝买东西支付密码错了怎么办 淘宝登入密码忘记了怎么办 逛街时手机没电了怎么办 逛街手机没有电了怎么办