题目大意:

动态单点更新,然后多次询问求区间内第k大

这里单个的主席树不能实现,这里采取的是树状数组套主席树

首先可以想的是将静态主席树先构建好,不去动它,这里空间复杂度就是O(nlogn),这个只要之前做过主席树的入门题的话就都不是问题

然后考虑更新的情况,这里将更新产生的前缀变化保存在树状数组中,那么每次更新都要更新logn棵树状数组上的主席树,每一棵的更新操作都是

logn次的,那么时间复杂度就是nlognlogn的只是可以承受的

之后的询问也是,预处理好用到的树状数组,然后保存到向量中,不断处理更新的值

 #include <bits/stdc++.h>

 using namespace std;
#define N 120010
#define lowbit(x) x&(-x)
#define define_m int m=(l+r)>>1
#define LS(x) node[x].ls
#define RS(x) node[x].rs vector<int> v1,v2; struct Node{
int ls , rs , sz;
Node(int ls= , int rs= , int sz=):ls(ls),rs(rs),sz(sz){}
void init(){ls=rs=sz=;}
}node[N*];
int tot , T1[N] , T2[N] , n , m , val[N]; //T1表示普通节点上的静态主席树,T2表示树状数组上的前缀树
int op[N] , s[N] , t[N] , rank[N]; int Hash(int v){return lower_bound(val , val+n , v)-val+;} int build(int l , int r)
{
int u = tot++;
node[u].init();
define_m;
if(l!=r){
LS(u) = build(l , m);
RS(u) = build(m+ , r);
}
return u;
} void build(int o1 , int o2 , int l , int r , int pos , int v , int i)
{
if(l==r){
node[o2].sz = node[o1].sz+v;
return;
}
define_m;
node[tot].init();
if(m>=pos){
LS(o2) = tot++ , RS(o2) = RS(o1);
build(LS(o1) , LS(o2) , l , m , pos , v , i);
}else{
LS(o2) = LS(o1) , RS(o2) = tot++;
build(RS(o1) , RS(o2) , m+ , r , pos , v , i);
}
node[o2].sz = node[LS(o2)].sz+node[RS(o2)].sz;
// cout<<"build : "<<i<<" "<<node[o2].sz<<" "<<l<<" "<<r<<" "<<pos<<endl;
} void update(int o , int l , int r , int pos , int v)
{
// cout<<pos<<" "<<l<<" "<<r<<" "<<v<<endl;
if(l==r){
node[o].sz += v;
return;
}
define_m;
if(m>=pos) {
if(!LS(o)){
LS(o) = tot++;
node[LS(o)].init();
}
update(LS(o) , l , m , pos , v);
}
else {
if(!RS(o)){
RS(o) = tot++;
node[RS(o)].init();
}
update(RS(o) , m+ , r , pos , v);
}
node[o].sz = node[LS(o)].sz+node[RS(o)].sz;
} void add(int x , int pos , int v)
{
while(x<=n){
if(!T2[x]){
node[tot].init();
T2[x] = tot++;
}
update(T2[x] , , n , pos , v);
x += lowbit(x);
}
} int query(vector<int> v1 , vector<int> v2 , int o1 , int o2 , int l , int r , int k)
{
// cout<<"fuck: "<<l<<" "<<r<<" "<<k<<endl;
if(l==r) return l;
define_m;
int c1 = node[LS(o2)].sz-node[LS(o1)].sz , l1=v1.size() , l2=v2.size();
// cout<<"st: "<<l1<<" "<<l2<<" "<<o1<<" "<<o2<<" "<<node[LS(o2)].sz<<" "<<node[LS(o1)].sz<<" "<<l<<" "<<r<<" "<<k<<endl;
for(int i= ; i<l1 ; i++){ c1-=node[LS(v1[i])].sz;
}
for(int i= ; i<l2 ; i++){
// if(node[LS(v2[i])].sz) cout<<"i: "<<i<<" "<<node[LS(v2[i])].sz<<endl;
c1+=node[LS(v2[i])].sz;
}
// cout<<"en: "<<l1<<" "<<l2<<" "<<o1<<" "<<o2<<" "<<c1<<" "<<l<<" "<<r<<" "<<k<<endl;
if(c1 >= k){
for(int i= ; i<l1 ; i++) v1[i] = LS(v1[i]);
for(int i= ; i<l2 ; i++) v2[i] = LS(v2[i]);
return query(v1 , v2 , LS(o1) , LS(o2) , l , m , k);
}else{
for(int i= ; i<l1 ; i++) v1[i] = RS(v1[i]);
for(int i= ; i<l2 ; i++) v2[i] = RS(v2[i]);
return query(v1 , v2 , RS(o1) , RS(o2) , m+ , r , k-c1);
}
} int query(int s , int t , int k)
{
v1.clear() , v2.clear();
int x = s-;
while(x>){
v1.push_back(T2[x]);
x-=lowbit(x);
}
x = t;
while(x>){
v2.push_back(T2[x]);
x-=lowbit(x);
}
return query(v1 , v2 , T1[s-] ,T1[t] , , n , k);
} char str[];
int cur[N]; int main()
{
//freopen("in.txt" , "r" , stdin);
//freopen("out1.txt" , "w" , stdout);
int T;
scanf("%d" , &T);
while(T--){
scanf("%d%d" , &n , &m);
tot = ;
for(int i= ; i<n ; i++){
scanf("%d" , val+i);
cur[i+] = val[i];
}
int cnt = n;
for(int i= ; i<m ; i++){
scanf("%s%d%d" , str , &s[i] , &t[i]);
if(str[] == 'Q'){
scanf("%d" , &rank[i]);
op[i] = ;
}
else{
op[i] = ;
val[cnt++] = t[i];
}
}
sort(val , val+cnt);
int pren = n;
n = unique(val , val+cnt)-val;
// cout<<pren<<" "<<n<<endl;
//初始建立静态主席树
T1[] = build( , n);
for(int i= ; i<=pren ; i++){
node[tot].init();
T1[i] = tot++;
build(T1[i-] , T1[i] , , n , Hash(cur[i]) , , i);
} memset(T2 , , sizeof(T2));
for(int i= ; i<m ; i++){
if(op[i]){
int pos = query(s[i] , t[i] , rank[i]);
printf("%d\n" , val[pos-]);
}else{
add(s[i] , Hash(cur[s[i]]) , -);
add(s[i] , Hash(t[i]) , );
cur[s[i]] = t[i];
}
}
}
return ;
}

zoj 2112 动态区间求第k大的更多相关文章

  1. 堆实战(动态数据流求top k大元素,动态数据流求中位数)

    动态数据集合中求top k大元素 第1大,第2大 ...第k大 k是这群体里最小的 所以要建立个小顶堆 只需要维护一个大小为k的小顶堆 即可 当来的元素(newCome)> 堆顶元素(small ...

  2. BZOJ2006:超级钢琴(ST表+堆求前K大区间和)

    Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度 ...

  3. poj 2985 The k-th Largest Group 树状数组求第K大

    The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8353   Accepted ...

  4. 【大杀器】利用划分树秒杀区间内第k大的数

    最近看了一道题,大概就是给出一个序列,不断询问其子区间内第k大的数,下面是个截图 绕了一圈没找到中文版题目,if(你是大佬) then 去看截图:else{我来解释:给出一个整数n,和一个整数m,分别 ...

  5. POJ 2985 Treap平衡树(求第k大的元素)

    这题也能够用树状数组做,并且树状数组姿势更加优美.代码更加少,只是这个Treap树就是求第K大元素的专家--所以速度比較快. 这个也是从那本红书上拿的模板--自己找了资料百度了好久,才理解这个Trea ...

  6. 算法导论学习之线性时间求第k小元素+堆思想求前k大元素

    对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思 ...

  7. 无序数组求第K大的数

    问题描述 无序数组求第K大的数,其中K从1开始算. 例如:[0,3,1,8,5,2]这个数组,第2大的数是5 OJ可参考:LeetCode_0215_KthLargestElementInAnArra ...

  8. 《数据结构与算法分析:C语言描述》读书笔记------练习1.1 求第K大的数

    求一组N个数中的第k个最大者,设k=N/2. import java.util.Random; public class K_Max { /** * @param args */ //求第K大的数,保 ...

  9. zoj2112 树状数组+主席树 区间动第k大

    Dynamic Rankings Time Limit: 10000MS   Memory Limit: 32768KB   64bit IO Format: %lld & %llu Subm ...

随机推荐

  1. Openfire 是怎么存离线消息

    原文:http://myopenfire.com/article/getarticle/26 1.openfire默认怎么存离线消息   在默认情况下,不添加任何插件的情况下,当用户不在线,对于发送给 ...

  2. ganymedssh2 java执行linux命令

    需要下载ganymed-ssh2-262.jar package ganymed; import java.io.BufferedReader; import java.io.IOException; ...

  3. C++模板(基础)

    本文转至:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html C++模板 模板是C++支持参数化多态的工具,使用模板可以使用户为类 ...

  4. 转:对TCP/IP网络协议的深入浅出归纳

    转自:http://blog.jobbole.com/74795/ 前段时间做了一个开发,涉及到网络编程,开发过程比较顺利,但任务完成后始终觉得有一些疑惑.主要是因为对网络协议不太熟悉,对一些概念也没 ...

  5. spring源码深度解析-2功能扩展

    容器功能的扩展ApplicationContext用于扩展BeanFactory中现有的功能.究竟多出了哪些功能,进一步探索.写法上:BeanFactory bf = new XmlBeanFacto ...

  6. java 多线程4(死锁)

    死锁现象: 死锁原因: 1.存在两个或两个以上的线程. 2.存在两个或两个或两个以上的共享资源. 死锁现象解决的方案: 没有方案只能尽量避免.

  7. docker居然需要3.10以上的内核

    本来想用下docker来安装部署多个MySQL实例呢,居然发现其需要3.10以上内核,对于使用centos6的人来说,是不能满足的. https://docs.docker.com/installat ...

  8. 【转】 Linux 线程同步的三种方法

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...

  9. [Eclipse] 详细设置护眼背景色和字体颜色并导出

    http://jingyan.baidu.com/article/d5a880eb6c4f7813f147ccef.html Eclipse是一款码农们喜闻乐见的集成开发平台,但是其默认的主题和惨白的 ...

  10. (04)odoo视图操作

    -----------------更新时间19:04 2016-09-29 星期四11:17 2016-09-18 星期日18:13 2016-04-05 星期二15:05 2016-03-14 星期 ...