n<=10000的序列做m<=10000个操作:单点修改,查区间第k小。

所谓的主席树也就是一个值域线段树嘛。。不过在这里还是%%fotile

需要做一个区间查询,由于查第k小,需要一些能够支持数值操作的东西,那就选择值域线段树,线段树上每个区间[L,R]表示的是值在L~R的数的相关信息,比如这里的“有多少个”。

不过呢这样的线段树没法维护区间下标怎么求区间信息啊,那就BIT套线段树,BIT上每个点表示一段区间(lowbit)的数值之和。为了空间,先离散化再动态开点效果拔群。

然后单点修改就该logn棵线段树,区间查询[L,R]就把R和L-1两个前缀的信息来相减。

这里第一次写树套树,见识了一种好操作!因为要同时操作很多棵线段树并且要在里面走来走去,就开一些指针一起走。那怎么知道谁要走呢?每次要区间查询时先init一下,把设计的线段树标记出来。由于两个前缀相减可能会有一些树标记到两次,那在前缀相减完之后这些标记两次的相当于不用算了,所以就把他们标记清除即可。

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
//#include<iostream>
using namespace std; int n,m;
#define maxn 20011
#define maxm 4000011 struct SMT
{
struct Node
{
int son[];
int l,r;
int cnt;
}a[maxm];
int size,n;
void clear(int m) {n=m;size=;a[].cnt=;}
void up(int x) {a[x].cnt=a[a[x].son[]].cnt+a[a[x].son[]].cnt;}
void insert(int &x,int L,int R,int num)
{
if (!x) {x=++size;a[x].l=L;a[x].r=R;a[x].cnt=;}
else a[x].cnt++;
if (L==R) return;
const int mid=(L+R)>>;
if (num<=mid) insert(a[x].son[],L,mid,num);
else insert(a[x].son[],mid+,R,num);
}
void insert(int &x,int num) {insert(x,,n,num);}
void Delete(int &x,int L,int R,int num)
{
a[x].cnt--;
if (!a[x].cnt) {x=;return;}
if (L==R) return;
const int mid=(L+R)>>;
if (num<=mid) Delete(a[x].son[],L,mid,num);
else Delete(a[x].son[],mid+,R,num);
}
void Delete(int &x,int num) {Delete(x,,n,num);}
}smt;
struct BIT
{
int a[maxn],t[maxn],n;
int vis[maxn];
void clear(int m) {n=m;memset(a,,sizeof(a));memset(vis,,sizeof(vis));}
void add(int x,int num) {for (;x<=n;x+=x&-x) smt.insert(a[x],num);}
void minus(int x,int num) {for (;x<=n;x+=x&-x) smt.Delete(a[x],num);}
void init(int x,int Time)
{for (;x;x-=x&-x) if (vis[x]!=Time) vis[x]=Time,t[x]=a[x];else vis[x]=;}
int query(int x,int Time)
{int ans=;for (;x;x-=x&-x) if (vis[x]==Time) ans+=smt.a[smt.a[t[x]].son[]].cnt;return ans;}
void turn(int x,int Time,int dir) {for (;x;x-=x&-x) if (vis[x]==Time) t[x]=smt.a[t[x]].son[dir];}
}t; struct Doo
{
bool type;int x,y,z;
}doo[maxn];
int lisan[maxn],a[maxn],li=;
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) scanf("%d",&a[i]),lisan[++li]=a[i];
for (int i=;i<=m;i++)
{
char c=' ';while (c!='Q' && c!='C') c=getchar();
if ((doo[i].type=(c=='Q'))) scanf("%d%d%d",&doo[i].x,&doo[i].y,&doo[i].z);
else scanf("%d%d",&doo[i].x,&doo[i].y),lisan[++li]=doo[i].y;
}
sort(lisan+,lisan++li);li=unique(lisan+,lisan++li)-lisan-;
for (int i=;i<=n;i++) a[i]=lower_bound(lisan+,lisan++li,a[i])-lisan;
for (int i=;i<=m;i++) if (!doo[i].type) doo[i].y=lower_bound(lisan+,lisan++li,doo[i].y)-lisan; t.clear(n);smt.clear(li);
for (int i=;i<=n;i++) t.add(i,a[i]);
for (int i=;i<=m;i++)
{
if (doo[i].type)
{
int x=doo[i].x-,y=doo[i].y,z=doo[i].z,l=,r=li,tmp;
t.init(y,i);t.init(x,i);
while (l<r)
{
if ((tmp=t.query(y,i)-t.query(x,i))>=z) r=(l+r)>>,t.turn(y,i,),t.turn(x,i,);
else l=((l+r)>>)+,z-=tmp,t.turn(y,i,),t.turn(x,i,);
}
printf("%d\n",lisan[l]);
}
else
{
t.minus(doo[i].x,a[doo[i].x]);
t.add(doo[i].x,(a[doo[i].x]=doo[i].y));
}
}
return ;
}

主席树初探--BZOJ1901: Zju2112 Dynamic Rankings的更多相关文章

  1. 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings

    谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...

  2. [BZOJ1901]Zju2112 Dynamic Rankings

    [BZOJ1901]Zju2112 Dynamic Rankings 试题描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i ...

  3. BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Submit: 6058 Solved: 2521 [Su ...

  4. BZOJ1901 Zju2112 Dynamic Rankings 主席树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1901 题意概括 给你一段序列(n个数),让你支持一些操作(共m次), 有两种操作,一种是询问区间第 ...

  5. [luogu2617][bzoj1901][Zju2112]Dynamic Rankings【树套树+树状数组+主席树】

    题目网址 [传送门] 题目大意 请你设计一个数据结构,支持单点修改,区间查询排名k. 感想(以下省略脏话inf个字) 真的强力吹爆洛谷数据,一般的树套树还给我T了一般的点,加强的待修主席树还给我卡了几 ...

  6. bzoj1901: Zju2112 Dynamic Rankings(BIT套主席树)

    带修改的题主席树不记录前缀,只记录单点,用BIT统计前缀.  对于BIT上每一个点建一棵主席树,修改和询问的时候用BIT跑,在主席树上做就行了.  3k4人AC的题#256...应该不算慢 #incl ...

  7. BZOJ1901 Zju2112 Dynamic Rankings 【树状数组套主席树】

    题目 给定一个含有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- ...

  8. 高级数据结构(树状数组套主席树):ZOJ 2112 Dynamic Rankings

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  9. BZOJ1901——Zju2112 Dynamic Rankings

    1.题目大意:区间第k小,有单点修改 2.分析:这个是树状数组套线段树,也是主席树....为什么主席树这么多QAQ 就是树套树的那种插入什么的,注意啊,一定要动态开内存..不然会爆.. 然后算答案有两 ...

随机推荐

  1. 设计模式 -- Abstract Factory 抽象工厂

    1.常规的对象创建方法 //创建一个Road对象 Road road=new Road(); new的问题:实现依赖,不能应对“具体实例化类型”额变化. 解决思想: 封装变化点--哪里变化,封装哪里( ...

  2. AJPFX关于Java Object类常用方法小总结

    java.lang.Object   java.lang包在使用的时候无需显示导入,编译时由编译器自动导入. Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类. Object类 ...

  3. AJPFX区分this和super

    this和super的区别No.区别thissuper1操作属性this.属性:表示调用本类中的属性,如果本类中的属性不存在,则从父类查找super.属性:表示调用父类中的属性2操作方法this.方法 ...

  4. spring中for循环中事务

    1.需求:批量插入一批数据,不用spring jdbc的批处理,用for循环插入数据. 2.遇到的问题:在for循环中,当一个插入不成功,前面插入成功的数据也将回滚. 3.初始设计:在service中 ...

  5. 掌握Spark机器学习库-06-基础统计部分

    说明 本章主要讲解基础统计部分,包括基本统计.假设检验.相关系数等 数据集 数据集有两个文件,分别是: beijing.txt 北京历年降水量,不带年份 beijing2.txt 北京历年降水量,带年 ...

  6. 从0开始搭建SQL Server 2012 AlwaysOn 第二篇(配置故障转移集群)

    本篇主要讲配置Windows 故障转移集群及遇到的相关问题(坑),因为AlwaysOn是基于Windows的故障转移集群的 在讲解步骤之前需要了解一下故障转移集群仲裁配置 四种集群的仲裁配置: 1.多 ...

  7. 调度工具taskctl跨调度服务依赖实现

    调度工具taskctl虽然支持分布式调度,但是有的时候,不同重要程度的调度服务还是要区分开来,在区分开后,不同调度服务之间怎么实现依赖啦, 其实有很多方式,比如写文件,写数据库之类的,这些都可以根据用 ...

  8. 关于Qt模态框总汇

    转载请注明出处:http://www.cnblogs.com/dachen408/p/7285710.html 父窗体为QMainWindow: 当子窗体为: 1.QWidget,需要设置 this- ...

  9. 洛谷 P3388 【模板】割点

    题目背景 割点 题目描述 给出一个n个点,m条边的无向图,求图的割点. 输入输出格式 输入格式: 第一行输入n,m 下面m行每行输入x,y表示x到y有一条边 输出格式: 第一行输出割点个数 第二行按照 ...

  10. [转载]iTOP-4418开发板Ubuntu系统烧写方法分享

    本文转自迅为论坛:http://topeetboard.com 开发平台:iTOP-4418开发板系统:Ubuntu 1. TF卡读写速度测试烧写 Ubuntu 对于 TF 卡的要求比较高,很多老旧的 ...