257. 动态排名系统

时间限制:5 s   内存限制:512 MB

[问题描述]
给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:
1、查询A[i],A[i+1],A[i+2],...,A[j](1<=i<=j<=N)中,升序排列后排名第k的数。
2、修改A[i]的值为j。
所谓排名第k,指一些数按照升序排列后,第k位的数。例如序列{6,1,9,6,6},排名第3的数是6,排名第5的数是9。
[输入格式]
第一行包含一个整数D(0<=D<=4),表示测试数据的数目。接下来有D组测试数据,每组测试数据中,首先是两个整数N(1<=N<=50000),M(1<=M<=10000),表示序列的长度为N,有M个操作。接下来的N个不大于1,000,000,000正整数,第i个表示序列A[i]的初始值。然后的M行,每行为一个操作
Q i j k 或者
C i j
分别表示查询A[i],A[i+1],A[i+2],...,A[j](1<=i<=j<=N)中,升序排列后排名第k的数,和修改A[i]的值为j。
[输出格式]
对于每个查询,输出一行整数,为查询的结果。测试数据之间不应有空行。
[样例输入]
2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
[样例输出]
3
6
3
6

题解:

(如果你没有听过“树状数组套主席树”这个概念,你选择可以移步我的讲解http://www.cnblogs.com/LadyLex/p/7275164.html

本题就是一个树状数组套主席树的板子题,如果用指针打的话操作时可以用vector存下需要更改的几棵树,进行修改

查询时候和普通的静态查询也是类似的,只不过是子树数据数量之和与k比较

这些东西还是通过代码可以更好的理解……代码见下:

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N=,MAXN=1000000000ll;
int n,val[N],tp;
struct node
{
node *ch[];int cnt;
node(){cnt=;ch[]=ch[]=NULL;}
inline void update(){cnt=ch[]->cnt+ch[]->cnt;}
}*null=new node(),*root[N*];
vector<node*>v[];
inline node* newnode()
{
node *o=new node();
o->ch[]=o->ch[]=null;
return o;
}
inline int lowbit(int a){return a&-a;}
inline void get_query(int id,int pos)
{
v[id].clear();
while(pos)v[id].push_back(root[pos]),pos-=lowbit(pos);
}
inline void get_set(int id,int pos)
{
v[id].clear();
while(pos<=n)v[id].push_back(root[pos]),pos+=lowbit(pos);
}
inline void set(vector<node*> o,int l,int r,int pos,int opt)
{
while(l<r)
{
int mi=(l+r)>>;
for(int i=,len=o.size();i<len;i++)if(o[i]!=null)o[i]->cnt+=opt;
if(pos<=mi)
{
r=mi;
for(int i=,len=o.size();i<len;o[i]=o[i]->ch[],i++)
if(o[i]->ch[]==null)o[i]->ch[]=newnode();
}
else
{
l=mi+;
for(int i=,len=o.size();i<len;o[i]=o[i]->ch[],i++)
if(o[i]->ch[]==null)o[i]->ch[]=newnode();
}
}
for(int i=,len=o.size();i<len;i++)
{
if(o[i]==null)o[i]=newnode();
o[i]->cnt+=opt;
}
}
inline int query(int a,int b,int l,int r,int k)
{
get_query(,a-);get_query(,b);
while(l<r)
{
int tmp=,mi=(l+r)>>;
for(int i=,len=v[].size();i<len;i++)if(v[][i]!=null)tmp-=v[][i]->ch[]->cnt;
for(int i=,len=v[].size();i<len;i++)if(v[][i]!=null)tmp+=v[][i]->ch[]->cnt;
if(tmp>=k)
{
for(int i=,len=v[].size();i<len;i++)v[][i]=v[][i]->ch[];
for(int i=,len=v[].size();i<len;i++)v[][i]=v[][i]->ch[];
r=mi;
}
else
{
for(int i=,len=v[].size();i<len;i++)v[][i]=v[][i]->ch[];
for(int i=,len=v[].size();i<len;i++)v[][i]=v[][i]->ch[];
k-=tmp,l=mi+;
}
}
return r;
}
inline void change(int a,int b)
{get_set(,a);set(v[],,MAXN,val[a],-);set(v[],,MAXN,b,);val[a]=b;}
int main()
{
int m,a,b,c;char s[];
null->ch[]=null->ch[]=null;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)root[i]=newnode();
for(int i=;i<=n;i++)scanf("%d",&val[i]),get_set(,i),set(v[],,MAXN,val[i],);
while(m--)
{
scanf("%s",s);
if(s[]=='Q')scanf("%d%d%d",&a,&b,&c),printf("%d\n",query(a,b,,MAXN,c));
else scanf("%d%d",&a,&b),change(a,b);
}
}

[COGS257]动态排名系统 树状数组套主席树的更多相关文章

  1. 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 ...

  2. [BZOJ3932] [CQOI2015]任务查询系统(主席树 || 树状数组 套 主席树 + 差分 + 离散化)

    传送门 看到这个题有个很暴力的想法, 可以每一个时间点都建一颗主席树,主席树上叶子节点 i 表示优先级为 i 的任务有多少个. 当 x 到 y 有个优先级为 k 的任务时,循环 x 到 y 的每个点, ...

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

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

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

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

  5. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

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

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

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

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

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

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

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

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

随机推荐

  1. Oracle EBS 配置文件取值

    SELECT op.profile_option_id, tl.profile_option_name, tl.user_profile_option_name, lv.level_id, lv.文件 ...

  2. 使用CocoaPods

    使用CocoaPods 1. 安装CocoaPods 有时候,默认的 https://rubygems.org/ 访问不了,你需要先执行以下命令移除掉sources gem sources -r ht ...

  3. Linux 环境部署记录(一) - 基础设定

    时间设置 查看系统当前日期/时间: date -R 查看系统硬件时钟: hwclock --show 设置硬件时间: hwclock --set --date="07/18/17 20:55 ...

  4. 《关于oracle数据库的勒索病毒的预警》

    近日,接部分机构反馈和安全厂商提醒,针对oracle数据库的勒索病毒攻击数量增加.该病毒存在较长潜伏期,会根据数据库实例创建时间距今是否满足1200天决定是否发起攻击.攻击通过执行恶意SQL脚本,加密 ...

  5. 一段滚动文字的js (jQuery)

    function startmarqueeOneSMS() { var t; var to; var ishover = false; var waitone = 3000; var speed = ...

  6. caioj 1172 poj 2823 单调队列过渡题

    给定一个n个数的数列,从左至右输出每个长度为m的数列段内的最大数. 输入:第一行两个整数n和m( 1<= n <= 20 0000,m<=n).下来给出n个整数. 输出:一行一个整数 ...

  7. python第八课——random模块的使用

    2.2.如何获取随机整数值? 引入random模块的使用 randint(a,b)函数:作用:返回给程序一个[a,b]范围内的随机整数注意:含头含尾闭区间 思路步骤: 第一步:导入random模块到相 ...

  8. 如何动态调用 C 函数

    JSPatch 支持了动态调用 C 函数,无需在编译前桥接每个要调用的 C 函数,只需要在 JS 里调用前声明下这个函数,就可以直接调用: require('JPEngine').addExtensi ...

  9. P2245 星际导航

    题目描述 sideman 做好了回到 Gliese星球的硬件准备,但是 sideman 的导航系统还没有完全设计好.为了方便起见,我们可以认为宇宙是一张有 N 个顶点和 M 条边的带权无向图,顶点表示 ...

  10. java web开发环境配置系列(二)安装tomcat

    在今天,读书有时是件“麻烦”事.它需要你付出时间,付出精力,还要付出一份心境.--仅以<java web开发环境配置系列>来祭奠那逝去的…… 1.下载tomcat压缩包,进入官网http: ...