题目大意

给定一个有N个数字的序列,然后又m个指令,指令种类只有两种,形式如下:

Q l r k 要求你查询区间[l,r]第k小的数是哪个

C i t  要求你把第i个数修改为t

题解

动态的区间第k小,如果还是按照静态的主席树做的话,每次修改需要对n个线段树进行修改,这样显然会TLE,所以我们需要用树状数组,这样每次只需要对logn颗线段树修改即可,修改的时间复杂度为logn^2,询问的时间复杂度为logn^2,空间复杂度为nlogn^2

还有一种空间复杂度为nlogn+mlogn^2的方法,就是先建立n颗静态的主席树,空间复杂度为nlogn,然后再更新的时候用树状数组套线段树,这样空间复杂度为mlogn^2,所以总空间复杂度为nlogn+mlogn^2

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 140000
#define NN 10005
#define lson l,m,ls[s]
#define rson m+1,r,rs[s]
int ls[*MAXN],rs[*MAXN],cnt[*MAXN];
int T[MAXN],tot;
int len,n,m;
int num[MAXN];
char op[][];
int a[NN*],lt[NN],rt[NN],K[NN];
int L[],R[];
int N,M;
void build(int l,int r,int &s)
{
s=++tot;
cnt[s]=;
if(l==r) return;
int m=(l+r)>>;
build(lson);
build(rson);
}
void update(int last,int p,int l,int r,int &s,int d)
{
s=++tot;
ls[s]=ls[last],rs[s]=rs[last],cnt[s]=cnt[last]+d;
if(l==r) return;
int m=(l+r)>>;
if(p<=m) update(ls[last],p,lson,d);
else update(rs[last],p,rson,d); }
int query(int l,int r,int k)
{
if(l==r) return r;
int suma=,sumb=;
for(int i=; i<=N; i++) suma+=cnt[ls[L[i]]];
for(int i=; i<=M; i++) sumb+=cnt[ls[R[i]]];
int m=(l+r)>>,sum=sumb-suma;
if(sum>=k)
{
for(int i=; i<=N; i++) L[i]=ls[L[i]];
for(int i=; i<=M; i++) R[i]=ls[R[i]];
return query(l,m,k);
}
else
{
for(int i=; i<=N; i++) L[i]=rs[L[i]];
for(int i=; i<=M; i++) R[i]=rs[R[i]];
return query(m+,r,k-sum);
}
}
int lowbit(int x)
{
return x&-x;
}
void BIT(int x,int value,int d)
{
while(x<=n)
{
update(T[x],value,,len,T[x],d);
x+=lowbit(x);
}
}
int BIT_query(int l,int r,int k)
{
N=,M=;
while(l>)
{
L[++N]=T[l];
l-=lowbit(l);
}
while(r>)
{
R[++M]=T[r];
r-=lowbit(r);
}
return query(,len,k);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
{
scanf("%d",&num[i]);
a[++len]=num[i];
}
for(int i=; i<=m; i++)
{
scanf("%s%d%d",op[i],&lt[i],&rt[i]);
if(op[i][]=='Q') scanf("%d",&K[i]);
else
a[++len]=rt[i];
}
sort(a+,a+len+);
len=unique(a+,a+len+)-a-;
for(int i=; i<=n; i++) num[i]=lower_bound(a+,a++len,num[i])-a;
build(,len,T[]);
for(int i=; i<=n; i++) BIT(i,num[i],);
for(int i=; i<=m; i++)
if(op[i][]=='Q')
printf("%d\n",a[BIT_query(lt[i]-,rt[i],K[i])]);
else
{
BIT(lt[i],num[lt[i]],-);
int pos=lower_bound(a+,a+len+,rt[i])-a;
num[lt[i]]=pos;
BIT(lt[i],pos,);
}
return ;
}

BZOJ1901 - Dynamic Rankings(树状数组套主席树)的更多相关文章

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

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

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

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

  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. 响应式布局中重要的meta标签设置.适用于手机浏览器兼容性设置

    <!-- #手机浏览器兼容性设置 -->    <meta content="application/xhtml+xml;charset=UTF-8" http- ...

  2. SQL sum case when then else【转】

    数据库 t 表     b 表内容        Id        Name      胜负        1          张三     胜        2          李四     ...

  3. poj 1818 ATP

    ATP 题意:足球锦标赛使用二分的策略,每次淘汰剩下人的一半,并且数据表明:排名相差k(include)之内的运动员,胜负难料,否则排名前的必定战胜排名后的:问给定n(n = 2x, x∈N, n & ...

  4. ArcGIS API for JavaScript 学习笔记(一)

    终于开始了 噩梦一般的ArcGIS 我特别不习惯这种结构化的程序写法 写起来特别吃力 特别是把几个功能整合到同一个页面去的时候. 写程序的时候,一般我喜欢先写个Demo然后再把Demo上面的功能加到页 ...

  5. Android初步 简单demo

    刚入门不久,没学JAVA,从C++转过来的,C++的QT和安卓简直有异曲同工之妙,为了加深自己对安卓的理解,特写博客以记录,望大神们多多指点. 效果图,刚入门的话,肯定要熟悉基本的控件的使用,这跟我学 ...

  6. EL四大作用域 9个jsp对象有效范围 及 对应的类

    java中request,session,application的作用范围 page,request,session,application四者的作用范围: page的作用范围是当前页面:对应El表达 ...

  7. C#基础|初探反射

    什么是反射 我们编写的C#代码都可以编译成exe文件或dll文件.暂时先把他们叫做程序集吧,程序集中包含了很多信息.你写了一个类,类中会有字段,有属性,有方法,编译是会把这些信息保存在程序集中,暂时把 ...

  8. ACM-进阶之路

    ACM进阶计划 ACM队不是为了一场比赛而存在的,为的是队员的整体提高. 大学期间,ACM队队员必须要学好的课程有: l C/C++两种语言 l 高等数学 l 线性代数 l 数据结构 l 离散数学 l ...

  9. java线程池的使用与详解

    java线程池的使用与详解 [转载]本文转载自两篇博文:  1.Java并发编程:线程池的使用:http://www.cnblogs.com/dolphin0520/p/3932921.html   ...

  10. Linux中crond服务与crontab用法

    需要写个在Linux下定时更新系统的脚本,man crondtab 不甚详细,现将网络上的介绍列举如下: crontab是一个很方便的在unix/linux系统上定时(循环)执行某个任务的程序使用cr ...