题目

给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1

],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改

变后的a继续回答上面的问题。

输入格式

第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。

分别表示序列的长度和指令的个数。

第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。

接下来的m行描述每条指令

每行的格式是下面两种格式中的一种。

Q i j k 或者 C i t

Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)

表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。

C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t

m,n≤10000

输出格式

对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

输入样例

5 3

3 2 1 4 7

Q 1 4 3

C 2 6

Q 2 5 3

输出样例

3

6

题解

很裸的板

树状数组维护区间,主席树维护树状数组每个节点权值信息

【debug弄得要死,调用时(1,tot)写成了(l,r) QAQ】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define lbt(x) (x & -x)
using namespace std;
const int maxn = 10005,maxm = 10000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
return out * flag;
}
int rt[maxn],A[maxn],B[2 * maxn],n,m,tot = 1,siz,N;
int sum[maxm],ls[maxm],rs[maxm],a[2][20];
struct Que{int opt,l,r,k;}Q[maxn];
int getn(int x){
int l = 1,r = tot,mid;
while (l <= r){
mid = l + r >> 1;
if (B[mid] < x) l = mid + 1;
else r = mid - 1;
}
return l;
}
void update(int& u,int l,int r,int pos,int v){
if (!u) u = ++siz; sum[u] += v;
if (l == r) return;
int mid = l + r >> 1;
if (mid >= pos) update(ls[u],l,mid,pos,v);
else update(rs[u],mid + 1,r,pos,v);
}
int query(int l,int r,int k){
if (l == r) return l;
int mid = l + r >> 1,t = 0;
for (int i = 1; i <= a[0][0]; i++) t += sum[ls[a[0][i]]];
for (int i = 1; i <= a[1][0]; i++) t -= sum[ls[a[1][i]]];
if (t >= k){
for (int i = 1; i <= a[0][0]; i++) a[0][i] = ls[a[0][i]];
for (int i = 1; i <= a[1][0]; i++) a[1][i] = ls[a[1][i]];
return query(l,mid,k);
}else {
for (int i = 1; i <= a[0][0]; i++) a[0][i] = rs[a[0][i]];
for (int i = 1; i <= a[1][0]; i++) a[1][i] = rs[a[1][i]];
return query(mid + 1,r,k - t);
}
}
void add(int u,int x,int v){while (u <= n) update(rt[u],1,tot,x,v),u += lbt(u);}
int solve(int l,int r,int k){
a[0][0] = a[1][0] = 0;
for (int i = r; i; i -= lbt(i)) a[0][++a[0][0]] = rt[i];
for (int i = l - 1; i; i -= lbt(i)) a[1][++a[1][0]] = rt[i];
return query(1,tot,k);
}
int main(){
n = read(); m = read(); char c;
REP(i,n) A[i] = B[++N] = read();
REP(i,m){
c = getchar(); while (c != 'Q' && c != 'C') c = getchar();
if (c == 'Q') Q[i].opt = 0,Q[i].l = read(),Q[i].r = read(),Q[i].k = read();
else Q[i].opt = 1,Q[i].l = read(),Q[i].k = B[++N] = read();
}
sort(B + 1,B + 1 + N);
for (int i = 2; i <= N; i++) if (B[i] != B[tot]) B[++tot] = B[i];
REP(i,n) A[i] = getn(A[i]),add(i,A[i],1);
REP(i,m){
if (!Q[i].opt) printf("%d\n",B[solve(Q[i].l,Q[i].r,Q[i].k)]);
else{
Q[i].k = getn(Q[i].k);
add(Q[i].l,A[Q[i].l],-1);
A[Q[i].l] = Q[i].k;
add(Q[i].l,A[Q[i].l],1);
}
}
return 0;
}

BZOJ1901 Zju2112 Dynamic Rankings 【树状数组套主席树】的更多相关文章

  1. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

  2. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

  3. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  4. LUOGU P2617 Dynamic Rankings(树状数组套主席树)

    传送门 解题思路 动态区间第\(k\)大,树状数组套主席树模板.树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和.然后询问的时候\(log\)个点一起做前缀和,一起移动.时空复杂度\(O ...

  5. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  6. BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树

    BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...

  7. [COGS257]动态排名系统 树状数组套主席树

    257. 动态排名系统 时间限制:5 s   内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...

  8. BZOJ 2141 排队(树状数组套主席树)

    解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...

  9. 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】

    题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...

  10. Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)

    E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...

随机推荐

  1. TypeScript 编译选项

    编译选项 选项 类型 默认值 描述 --allowJs boolean false 允许编译javascript文件. --allowSyntheticDefaultImports boolean m ...

  2. 如何着手学习一个新的PHP框架

    如今的PHP框架层出不穷,名气也各不相同.如何快速掌握一种框架?看看本文吧~ 如今的PHP框架层出不穷,名气也各不相同.我不是这方面的专家,甚至不能熟练地使用其中的一种,所以就不作推荐了.这里我要讨论 ...

  3. CXF学习记录

    1 apache CXF入门 1.1 下载 官网:cxf.apache.org 下载CXF的开发包: Apache CXF = Celtix + Xfire 支持多种协议: SOAP1.1,1.2 X ...

  4. java算法面试题:从类似如下的文本文件中读取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序 ;读取docx 读取doc 使用poi 相关jar包提集提供下载

    从类似如下的文本文件中读取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序 1,张三,28 2,李四,35 3,张三,28 4,王五,35 5,张三,28 6,李四,35 7,赵六,28 ...

  5. oc字符串截取 数组字典运用

    #define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS_ ...

  6. Smallest Common Multiple-freecodecamp算法题目

    Smallest Common Multiple 1.要求 找出能被两个给定参数和它们之间的连续数字整除的最小公倍数. 2.思路 设定一个twoMultiple(a,b)函数,求出输入两个参数的最小公 ...

  7. jstl(c)标签

    一.EL表达式: Expression Language提供了在 JSP 脚本编制元素范围外(例如:脚本标签)使用运行时表达式的功能.脚本编制元素是指页面中能够用于在JSP 文件中嵌入 Java 代码 ...

  8. 树莓派下ubuntu-mate中ssh服务的安装与开机后自启动

    ssh程序分为客户端程序openssh-client和服务端程序openssh-server. 如果需要ssh登陆到别的电脑,需要安装openssh-client,该程序ubuntu是默认安装的.而如 ...

  9. SpringBoot-Security-用户权限分配-项目搭建

    SpringBoot原则是约定优于配置,简化spring应用开发,去繁从简,产品级别的应用. SpringBoot有哪些优点1.快速创建独立运行的spring项目与主流框架集成 2.使用嵌入式的ser ...

  10. CodeForces 781D Axel and Marston in Bitland DP

    题意: 有一个\(n\)个点\(m\)条边的无向图,边有两种类型,分别用\(0\)和\(1\)标识 因此图中的任意一条路径都对应一个\(01\)字符串 定义一个无限长的字符串\(s\): 开始令\(s ...