BZOJ1901 Zju2112 Dynamic Rankings 主席树
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1901
题意概括
给你一段序列(n个数),让你支持一些操作(共m次),
有两种操作,一种是询问区间第k小,一种是单点修改。
n,m<=10000
题解
这个主席树的写法是我自己造出来的。
主席树的查询区间第k大需要依赖前缀和。
树状数组最擅长这个了,就让他来干。
原理是这样的:
先离散化,包括修改操作里面的数字也要离散化。
然后建树,包括修改操作所涉及的数值也要建。
现在总共有n个线段树。
第0棵树是最完整的,故我们把这棵树的每一个节点都当作一个树状数组的起点,即该树状数组的第一项。
然后往下一棵树走,当然下一棵树不一定有这个节点,那么不停的走下去,这个可以在建树的时候预先处理一个Next数组来优化。
走到下一个这个位置的节点之后,我们再把这个节点作为该树状数组的第二项。
这样我们有大约n*4(第0棵树的节点个数)个树状数组了。
然而不处理要超空间。
所以有两种方案,一种是vector,一种是把所有的树状数组连起来,变成一个大的。
然而查询之类的就和普通的主席树差不多了。
细节上要大大的注意!
代码
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
using namespace std;
const int N=10005,S=N*2*20*4;//v=4*node=4*20*hs=4*20*2*n
struct Que{
char op;
int a,b,c;
void read(){
char opc[5];
scanf("%s%d%d",opc,&a,&b);
op=opc[0];
if (op=='Q')
scanf("%d",&c);
}
}q[N];
vector <int> vec[N];
int n,m,v[N],Ha[N*2],hs=0,total=0,totarr=0;
int root[N],ls[S],rs[S],sum[S],pos[S],Next[S],p[S];
void LSH(){
int hs_=1;
sort(Ha+1,Ha+hs+1);
for (int i=2;i<=hs;i++)
if (Ha[i]!=Ha[i-1])
Ha[++hs_]=Ha[i];
hs=hs_;
}
int find(int x){
int L=1,R=hs,mid;
while (L<=R){
mid=(L+R)>>1;
if (Ha[mid]==x)
return mid;
if (Ha[mid]<x)
L=mid+1;
else
R=mid-1;
}
exit(233);
}
int build(int L,int R){
int rt=++total;
if (L==R){
ls[rt]=rs[rt]=0;
return rt;
}
int mid=(L+R)>>1;
ls[rt]=build(L,mid);
rs[rt]=build(mid+1,R);
return rt;
}
int lowbit(int x){
return x&-x;
}
void add(int x,int v){
for (;x<=totarr;x+=lowbit(x))
sum[x]+=v;
}
int Sum(int x){
int ans=0;
for (;x>0;x-=lowbit(x))
ans+=sum[x];
return ans;
}
void add_tree(int prt,int &rt,int L,int R,int pos){
if (!rt||rt==prt)
rt=++total;
Next[prt]=rt;
if (L==R)
return;
int mid=(L+R)>>1;
if (pos<=mid){
add_tree(ls[prt],ls[rt],L,mid,pos);
if (!rs[rt])
rs[rt]=rs[prt];
}
else {
add_tree(rs[prt],rs[rt],mid+1,R,pos);
if (!ls[rt])
ls[rt]=ls[prt];
}
}
void build_treearr(int srt,int L,int R){
for (int i=srt;i;i=Next[i])
p[i]=++totarr;
if (L==R)
return;
int mid=(L+R)>>1;
build_treearr(ls[srt],L,mid);
build_treearr(rs[srt],mid+1,R);
}
void update(int rt,int L,int R,int pos,int v){
add(p[rt],v);
if (L==R)
return;
int mid=(L+R)>>1;
if (pos<=mid)
update(ls[rt],L,mid,pos,v);
else
update(rs[rt],mid+1,R,pos,v);
}
int query(int prt,int rt,int L,int R,int k){
if (L==R)
return Ha[L];
int mid=(L+R)>>1;
int LV=Sum(p[ls[rt]])-Sum(p[ls[prt]]);
if (k<=LV)
return query(ls[prt],ls[rt],L,mid,k);
else
return query(rs[prt],rs[rt],mid+1,R,k-LV);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&v[i]),Ha[++hs]=v[i];
for (int i=1;i<=m;i++){
q[i].read();
if (q[i].op=='C')
Ha[++hs]=q[i].b;
}
LSH();
for (int i=1;i<=n;i++)
vec[i].clear();
for (int i=1;i<=n;i++)
vec[i].push_back(v[i]);
for (int i=1;i<=m;i++)
if (q[i].op=='C')
vec[q[i].a].push_back(q[i].b);
memset(sum,0,sizeof sum);
memset(pos,0,sizeof pos);
memset(Next,0,sizeof Next);
memset(root,0,sizeof root);
root[0]=build(1,hs);
for (int i=1;i<=n;i++)
for (int j=0;j<vec[i].size();j++)
add_tree(root[i-1],root[i],1,hs,find(vec[i][j]));
build_treearr(root[0],1,hs);
for (int i=1;i<=n;i++)
update(root[i],1,hs,find(v[i]),1);
for (int i=1;i<=m;i++)
if (q[i].op=='C'){
update(root[q[i].a],1,hs,find(v[q[i].a]),-1);
update(root[q[i].a],1,hs,find(v[q[i].a]=q[i].b),1);
}
else
printf("%d\n",query(root[q[i].a-1],root[q[i].b],1,hs,q[i].c));
return 0;
}
BZOJ1901 Zju2112 Dynamic Rankings 主席树的更多相关文章
- 【BZOJ1901】Zju2112 Dynamic Rankings 主席树+树状数组
[BZOJ1901]Zju2112 Dynamic Rankings Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j ...
- Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6321 Solved: 2628[Su ...
- bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1] ...
- [luogu2617][bzoj1901][Zju2112]Dynamic Rankings【树套树+树状数组+主席树】
题目网址 [传送门] 题目大意 请你设计一个数据结构,支持单点修改,区间查询排名k. 感想(以下省略脏话inf个字) 真的强力吹爆洛谷数据,一般的树套树还给我T了一般的点,加强的待修主席树还给我卡了几 ...
- 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- ...
- [bzoj1901][Zju2112]Dynamic Rankings_主席树
Dynamic Rankings bzoj-1901 Zju-2112 题目大意:给定一个n个数的序列,m个操作,支持:单点修改:查询区间k小值. 注释:$1\le n,m\le 10^4$. 想法: ...
- [BZOJ1901]Zju2112 Dynamic Rankings
[BZOJ1901]Zju2112 Dynamic Rankings 试题描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i ...
- BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Submit: 6058 Solved: 2521 [Su ...
- bzoj1901: Zju2112 Dynamic Rankings(BIT套主席树)
带修改的题主席树不记录前缀,只记录单点,用BIT统计前缀. 对于BIT上每一个点建一棵主席树,修改和询问的时候用BIT跑,在主席树上做就行了. 3k4人AC的题#256...应该不算慢 #incl ...
随机推荐
- JS知识整理之 Call&Apply方法
JavaScript中的函数也是对象,和其他JS对象一样也可以包含方法,其中Call和Apply就是其中比较重要的方法,可以用来间接的调用函数.这两个方法允许显式制定调用所需的this值,也就是说所有 ...
- 用Emacs的这些年
读技术博客时发现又有人提起我曾写的那篇口水文章 为何Emacs和Vim被称为两大神器.写那篇文章时,我还在Vim和Emacs之间摇摆.当然主要在用vim,博士学位论文和所有的国际会议文章都是用Vim编 ...
- asp.net mvc 中[Authorize]在IE9以上版本关于FormsAuthentication.SetAuthCookie无效的问题 解决方案
简单的解决方法是,在网站根目录,新增一个浏览器定义文件(browser definition file) 叫“App_Browsers”文件夹,然后里面放一个“IE10.browser”文件即可,网站 ...
- VS2012 安装番茄插件
1.visual assist x 1929_大番茄.rar 下载地址: http://pan.baidu.com/s/1qXOUuJE 网盘提取密码: 3mka 文件解压密码: eg5p 2.安装完 ...
- C++中构造函数和析构函数的调用顺序
一般而言,析构函数调用的顺序和构造函数调用顺序相反,但是,对象的存储类别可以改变调用析构函数的顺序.举例说明: CreateAndDestroy类的定义 CreateAndDestroy类的成员函数的 ...
- Protobuf使用手册
Protobuf使用手册 第1章 定义.proto 文件 首先我们需要编写一个 proto 文件,定义我们程序中需要处理的结构化数据,在 protobuf 的术语中,结构化数据被称为 Message. ...
- Linux mmc framework1:软件架构
[部分内容来自] http://www.wowotech.net/comm/mmc_framework_arch.html 1. 前言 由eMMC基础技术1:MMC简介中MMC.SD.SDIO的介绍可 ...
- malloc()函数(Linux程序员手册)及函数的正确使用【转】
转自:https://blog.csdn.net/david_xtd/article/details/7311204 名称 malloc,free,calloc,realloc--分配和释放动态内存 ...
- linux 串口0x03,0x13的问题【转】
linux 串口0x03,0x13的问题 本人最近在调linux串口的时候,发现其他数据接收正常,但是0x13怎么也接收不到,后面发现了这篇文章,两天的bug终于解决了,原来是linux底层uart配 ...
- SCons: 替代 make 和 makefile 及 javac 的极好用的c、c++、java 构建工具
http://scons.org/ https://www.ibm.com/developerworks/cn/linux/l-cn-scons/index.html 后附:另外,WAF是一个基于sc ...