题目描述

给出序列 a1,a2,…,an(0≤ai≤109),有关序列的两种操作。

1. ai(1≤i≤n)变成 x(0≤x≤109)。

2. 求 al,al+1,…,ar(1≤l≤r≤n)第 k(1≤k≤r-l+1)小。

输入格式

第一行包含两个数 n(1≤n≤2×104)和 m(1≤m≤2×104),表示序列长度和操作次数。

接下来一行 n 个数,以空格隔开,表示 a1,a2,…,an 。

接下来m行,每行为以下两种格式之一:

    • 0 i x ,  表示 ai=x。
    • 1 l r k ,求 al,al+1,…,ar 的第 k 小。

输出格式

对于每次询问,输出单独的一行表示答案。

样例数据 1

输入

5 3 
1 2 3 4 5 
1 1 5 3 
0 3 5 
1 1 5 3

输出


4

题目分析

本题有多种解法。这里先讲一下较为简单的树状数组套线段树。

外层树状数组n个节点分别对应下标,每个节点其实是一个权值为下标的线段树的根节点(一共有n颗),那么树状数组中的i号点表示的就是区间为1~i的元素,而其下的权值线段树则记录在该区间的权值出现次数。

由于树状数组有前缀和的性质,插入时会更新它及其以后的所有树,询问时也能访问它及其以前的所有树,所以要查询L~R的k小,就只需要将有关区间的点放入一个数组,然后分别进入左子树、右子树查询即可。

看看代码很好理解。

code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std; const int N = 2e4 + , M = 2e6 + ;
int len, a[N], b[N * ], root[N], tot;
int cur[N], n, m;
struct node{
int cnt, lc, rc;
}tr[M];
struct qry{
int opt, a, b, c;
}Q[N]; inline int read(){
int i = , f = ; char ch = getchar();
for(; (ch < '' || ch > '') && ch != '-'; ch = getchar());
if(ch == '-') f = -, ch = getchar();
for(; ch >= '' && ch <= ''; ch = getchar())
i = (i << ) + (i << ) + (ch - '');
return i * f;
} inline void wr(int x){
if(x < ) putchar('-'), x = -x;
if(x > ) wr(x / );
putchar(x % + '');
} inline void disc_init(){
sort(b + , b + len + );
len = unique(b + , b + len + ) - (b + );
for(int i = ; i <= n; i++)
a[i] = lower_bound(b + , b + len + , a[i]) - b;
for(int i = ; i <= m; i++)
if(Q[i].opt == ) Q[i].b = lower_bound(b + , b + len + , Q[i].b) - b;
}
inline void insert(int &k, int l, int r, int p, int v){
if(!k) k = ++tot;
tr[k].cnt += v;
if(l == r) return;
int mid = l + r >> ;
if(p <= mid) insert(tr[k].lc, l, mid, p, v);
else insert(tr[k].rc, mid + , r, p, v);
} inline void update(int k, int p, int v){
for(int i = k; i <= n; i += (i & -i))
insert(root[i], , len, p, v);
} inline void gotoPos(int lx, int rx){
for(int i = rx; i > ; i -= (i & -i)) cur[i] = root[i];
for(int i = lx; i > ; i -= (i & -i)) cur[i] = root[i];
} inline int CntLc(int lx, int rx){
int ret = ;
for(int i = rx; i > ; i -= (i & -i)) ret += tr[tr[cur[i]].lc].cnt;
for(int i = lx; i > ; i -= (i & -i)) ret -= tr[tr[cur[i]].lc].cnt;
return ret;
} inline int query(int nl, int nr, int l, int r, int k){
if(l == r) return l;
int ret = CntLc(nl, nr), mid = l + r >> ;
if(ret >= k){
for(int i = nr; i > ; i -= (i & -i)) cur[i] = tr[cur[i]].lc;
for(int i = nl; i > ; i -= (i & -i)) cur[i] = tr[cur[i]].lc;
return query(nl, nr, l, mid, k);
}
else{
for(int i = nr; i > ; i -= (i & -i)) cur[i] = tr[cur[i]].rc;
for(int i = nl; i > ; i -= (i & -i)) cur[i] = tr[cur[i]].rc;
return query(nl, nr, mid + , r, k - ret);
}
} inline void tree_init(){
for(int i = ; i <= n; i++) update(i, a[i], );
} int main(){
n = read(), m = read();
for(int i = ; i <= n; i++) a[i] = b[++len] = read();
for(int i = ; i <= m; i++){
Q[i].opt = read();
if(Q[i].opt == )
Q[i].a = read(), Q[i].b = read(), Q[i].c = read();
else Q[i].a = read(), Q[i].b = b[++len] = read();
}
disc_init();
tree_init();
for(int i = ; i <= m; i++){
if(Q[i].opt == ){
update(Q[i].a, a[Q[i].a], -);
a[Q[i].a] = Q[i].b;
update(Q[i].a, Q[i].b, );
}
else{
gotoPos(Q[i].a - , Q[i].b);
wr(b[query(Q[i].a - , Q[i].b, , len, Q[i].c)]), putchar('\n');
}
}
}

【序列操作IV】树状数组套线段树/树套树的更多相关文章

  1. 【BZOJ3196】二逼平衡树(树状数组,线段树)

    [BZOJ3196]二逼平衡树(树状数组,线段树) 题面 BZOJ题面 题解 如果不存在区间修改操作: 搞一个权值线段树 区间第K大--->直接在线段树上二分 某个数第几大--->查询一下 ...

  2. HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Tota ...

  3. st表、树状数组与线段树 笔记与思路整理

    已更新(2/3):st表.树状数组 st表.树状数组与线段树是三种比较高级的数据结构,大多数操作时间复杂度为O(log n),用来处理一些RMQ问题或类似的数列区间处理问题. 一.ST表(Sparse ...

  4. POJ 1195 Mobile phones (二维树状数组或线段树)

    偶然发现这题还没A掉............速速解决了............. 树状数组和线段树比较下,线段树是在是太冗余了,以后能用树状数组还是尽量用......... #include < ...

  5. HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)

    Jam's problem again Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  6. Codeforces 777E(离散化+dp+树状数组或线段树维护最大值)

    E. Hanoi Factory time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  7. HYSBZ - 3813 奇数国 欧拉函数+树状数组(线段树)

    HYSBZ - 3813奇数国 中文题,巨苟题,巨无敌苟!!首先是关于不相冲数,也就是互质数的处理,欧拉函数是可以求出互质数,但是这里的product非常大,最小都2100000,这是不可能实现的.所 ...

  8. 洛谷P3374 【模板】树状数组 1&&P3368 【模板】树状数组 2题解

    图片来自度娘~~ 树状数组形如上图,是一种快速查找区间和,快速修改的一种数据结构,一个查询和修改复杂度都为log(n),树状数组1和树状数组2都是板子题,在这里进行详解: 求和: 首先我们看一看这个图 ...

  9. 洛谷P3380 【模板】二逼平衡树(树套树,树状数组,线段树)

    洛谷题目传送门 emm...题目名写了个平衡树,但是这道题的理论复杂度最优解应该还是树状数组套值域线段树吧. 就像dynamic ranking那样(蒟蒻的Sol,放一个link骗访问量233) 所有 ...

  10. ZJOI 2017 树状数组(线段树套线段树)

    题意 http://uoj.ac/problem/291 思路 不难发现,九条カレン醬所写的树状数组,在查询区间 \([1,r]\) 的时候,其实在查询后缀 \([r,n]\) :在查询 \([l,r ...

随机推荐

  1. win10系统64位安装git后右键运行git bash here生成一个mintty.exe.stackdump文件后闪退解决方案

    在其他win10电脑上复制了一个null.sys文件,替换C:\Windows\System32\drivers\null.sys,搞定.

  2. Java Web学习总结(3)——Servlet详解

    一.ServletConfig讲解 1.1.配置Servlet初始化参数 在Servlet的配置文件web.xml中,可以使用一个或多个<init-param>标签为servlet配置一些 ...

  3. Serializable中的serialVersionUID到底有啥用

    最近在研究跨进程通信的问题,于是又再一次研究了,我们熟悉而又陌生的Serializable接口. 那么好,做过Java开发的朋友肯定对这个接口不陌生吧,Java中就是通过这个接口,来实现了序列化和反序 ...

  4. BZOJ——T2190: [SDOI2008]仪仗队

    Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 3216  Solved: 2075[Submit][Status][Discuss] http://w ...

  5. 【Codeforces Round #433 (Div. 2) A】Fraction

    [链接]h在这里写链接 [题意] 在这里写题意 [题解] 枚举分子从高到低就好. 这样得到的一定是最大的. (可以约分没错,但是约分过后和就不是n了,所以不会有错的) [错的次数] 0 [反思] 在这 ...

  6. C#游戏开发高速入门 2.1 构建游戏场景

    C#游戏开发高速入门 2.1  构建游戏场景 假设已经计划好了要编写什么样的游戏,在打开Unity以后.要做的第一件事情就是构建游戏场景(Scene).游戏场景就是玩家游戏时,在游戏视图中看到的一切. ...

  7. NSDate时间

    NSDate 使用 ios时间的秒数 取当前时间的秒数 NSTimeInterval time = [[NSDate date] timeIntervalSince1970]; long long i ...

  8. 第一个hello word 驱动载入失败--------

    今天尝试自己载入第一个驱动模块,依据惯例hello word 然后失败了,如今说明我的操作过程.请个位看看. 首先我的内核版本号: 模块代码与MAKEFILE #include<linux/in ...

  9. VMware Ubuntu安装具体过程

    不是每个程序猿都必须玩过linux,仅仅是博主认为如今的非常多server都是linux系统的,而自己属于那种前端也搞.后台也搞,对框架搭建也感兴趣,可是非常多生产上的框架和工具都是安装在server ...

  10. easyui datagrid editor checkbox 单击事件

    Easyui datagrid treegrid中能够为行追加checkbox元素.比如: $('#tt').treegrid({ url:'get_data.php', idField:'id', ...