1901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 8144  Solved: 3378
[Submit][Status][Discuss]

Description

给定一个含有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继续回答上面的问题。

Input

第一行一个数字N,代表测试组数
对于每组数据第一行有两个正整数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

Output

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

Sample Input

1
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

Sample Output

3
6

回想一样不带修改的区间第K大

离散化+去重就不说了,n个点分别建立n棵线段树

第i棵线段树中保存前i个数中每个数出现的个数

这样每次查询区间[a, b]时直接将第b棵树减去第a-1棵树就可以logn查询了

但是要修改怎么办呢

……

先记录所有查询和修改,将一开始的数和后来修改出现的数离散化+去重

假设暴力修改第i个数的话,的确可以logn的复杂度修改当前树的结构,但是后面所有的树都必须修改

单次复杂度是O((n-i+1)*logn)的,肯定超时

……

想想简单的问题:

①给你n个数m次查询每次查一个区间[L, R]所有数之和

方法:直接记录前缀和然后答案就是sum[R]-sum[L-1]

②给你n个数m次查询每次查一个区间[L, R]所有数之和,但可以修改某个数的值

这个时候前缀和的方法就没用了,只能树状数组

……

其实查询区间第k大和带修改的区间第k大和上面那两个问题是一样的

对于只查询的,就前缀和两棵树相减

对于带修改的,就树状数组套主席树就好了

……

这样暴力修改第i个树的话,只用修改log(n-i+1)棵树,单次复杂度O(log(n-i+1)*logn),查询同理(也是logn)

总复杂度O(nlognlogn)

注意真实的题目并没有T组输入,是单实例

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n, m, size, cnt, c, d, b[20005], t[10005], a[10005], L[10005], R[10005], k[10005], low[10005], up[10005];
typedef struct
{int l, r;int size;
}Ctree;
Ctree s[3000005];
int lowbit(int x){  return x&-x;  }
int Build(int l, int r);
int Update(int root, int x, int val);
int Query(int sum);
int main(void)
{char ch;int i, j, x;while(scanf("%d%d", &n, &m)!=EOF){cnt = 0, size = n;for(i=1;i<=n;i++){scanf("%d", &a[i]);b[i] = a[i];}memset(R, -1, sizeof(R));memset(s, 0, sizeof(s));for(i=1;i<=m;i++){scanf(" %c", &ch);if(ch=='Q')scanf("%d%d%d", &L[i], &R[i], &k[i]);else{scanf("%d%d", &L[i], &k[i]);b[++size] = k[i];}}sort(b+1, b+size+1);size = unique(b+1, b+size+1)-(b+1);t[1] = Build(1, size);for(i=2;i<=n;i++)t[i] = t[1];for(i=1;i<=n;i++){x = lower_bound(b+1, b+size+1, a[i])-b;for(j=i;j<=n;j+=lowbit(j))t[j] = Update(t[j], x, 1);}for(i=1;i<=m;i++){if(R[i]==-1){x = lower_bound(b+1, b+size+1, a[L[i]])-b;for(j=L[i];j<=n;j+=lowbit(j))t[j] = Update(t[j], x, -1);a[L[i]] = k[i];x = lower_bound(b+1, b+size+1, a[L[i]])-b;for(j=L[i];j<=n;j+=lowbit(j))t[j] = Update(t[j], x, 1);}else{c = d = 0;for(j=L[i]-1;j>=1;j-=lowbit(j))low[++c] = t[j];for(j=R[i];j>=1;j-=lowbit(j))up[++d] = t[j];printf("%d\n", b[Query(k[i])]);}}}return 0;
}int Build(int l, int r)
{int m, root;root = ++cnt;m = (l+r)/2;s[root].size = 0;if(l==r)return root;s[root].l = Build(l, m);s[root].r = Build(m+1, r);return root;
}int Update(int root, int x, int val)
{int now, tmp, l, r, m;tmp = now = ++cnt;l = 1, r = size;while(l<r){s[now].size = s[root].size+val;m = (l+r)/2;if(x<=m){s[now].l = ++cnt;s[now].r = s[root].r;root = s[root].l;now = cnt;r = m;}else{s[now].l = s[root].l;s[now].r = ++cnt;root = s[root].r;now = cnt;l = m+1;}}s[now].size = s[root].size+val;return tmp;
}
int Query(int sum)
{int l, r, m, i, now;l = 1, r = size;while(l<r){now = 0;m = (l+r)/2;for(i=1;i<=d;i++)now += s[s[up[i]].l].size;for(i=1;i<=c;i++)now -= s[s[low[i]].l].size;if(now>=sum){for(i=1;i<=d;i++)up[i] = s[up[i]].l;for(i=1;i<=c;i++)low[i] = s[low[i]].l;r = m;}else{sum -= now;for(i=1;i<=d;i++)up[i] = s[up[i]].r;for(i=1;i<=c;i++)low[i] = s[low[i]].r;l = m+1;}}return r;
}

bzoj 1901: Zju2112 Dynamic Rankings(离线树状数组+主席树)相关推荐

  1. 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树

    题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见-- 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...

  2. COGS-257-动态排名系统-树状数组+主席树

    描述 给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作: 1.查询A[i],A[i+1],A[i+2],...,A[j](1<=i< ...

  3. 线。段。树--树状数组-主席树

    简单了解一下线段树 以前写过的内容,搬运过来 线段树的应用场景:满足区间加法性质且多次查询,什么是区间加法性质,比如最大值,求和,树状数组.线段树.主席树依次. 线段树框架:建树--查询--更新... ...

  4. Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 6321  Solved: 2628 [ ...

  5. 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1901 首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊. ...

  6. bzoj 1901: Zju2112 Dynamic Rankings

    Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 6245  Solved: 2593 [Submit][Status][Discuss] Descri ...

  7. 洛谷 - P2163 [SHOI2007]园丁的烦恼(不带修二维数点-树状数组/主席树)

    题目链接:点击查看 题目大意:二维平面坐标系中给出 nnn 个坐标点,然后是 mmm 次询问,每次询问需要回答一个闭合矩阵中有多少个点 题目分析:想挂树套树来着,但是复杂度有点大.本题不带修且可以离线 ...

  8. HDU 3333 Turing Tree(树状数组/主席树)

    题意 给定一个长度为 \(n​\) 的序列,\(m​\) 个查询,每次查询区间 \([L,R]​\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...

  9. hdu 4417 Super Mario 树状数组||主席树

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Prob ...

最新文章

  1. php display_errors
  2. 如何创建高质量的TypeScript声明文件(六) - 示例
  3. [leetcode]@python 85. Maximal Rectangle
  4. Dubbo接口测试方法及步骤
  5. ADS1.2开发环境创建与简要介绍
  6. 信息学奥赛一本通 1152:最大数max(x,y,z)
  7. python加密字符串小写字母循环后错两位_python数据类型_字符串常用操作(详解)
  8. 安装mysql会有驱动吗_kettle 安装mysql 驱动
  9. java 题库管理系统_JAVA WEB 题库管理系统
  10. 创业公司专题数据(包含stata多种模型代码)
  11. 从论文pdf中复制粘贴文字时,空格变成回车的解决方法
  12. 保留(私有)地址简介
  13. PyCharm快捷键——搜索/替换快捷键
  14. 数据科学导引——租车人数预测模型 线性回归模型
  15. Android Studio的Signature Versions选择,分别是什么意思
  16. sharing-jdbc分库分表方案设计
  17. mysql情况数据库表数据函数_mysql数据库表单查询和函数的使用
  18. tesla k80显卡 配置支持opengl
  19. Github最受欢迎的10大深度学习时间序列项目
  20. linux安装tesseract支持tess4j图片识别

热门文章

  1. python接口自动化参数化_python接口自动化-参数化
  2. Vue图片上传删除预览操作
  3. 在设备上添加项目失败_使用VisualGDB将Keil项目导入VisualStudio
  4. 实现深拷贝的常用方法
  5. 【二分法】计蒜客:求方程的近似解
  6. LIRe 源代码分析 4:建立索引(DocumentBuilder)[以颜色布局为例]
  7. VC 2008 Express下安装OpenCV2.3.1
  8. mysql保存表出错1075_navicat出现错误1075怎么办
  9. 怎么用Android做一个信息管理系统,从零开始设计一个管理系统
  10. java double 存储_可以存储在double中的最大整数