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. c# -反射 初见

    反射是一个很强大的功能,不过好像有些消耗性能,大家慎重使用. 1.反射是干什么的? 通过反射,我们可与获取程序集中的原数据. 1.什么是程序集? dll.exe  这些将很多能实现具体功能的代码封装起 ...

  2. 《基于Node.js实现简易聊天室系列之环境搭建》

    前文提到了Demo所涉及的技术,现在讲环境(工具)的配置.环境的配置主要是数据库mongDB和Node.js的配置. Node.js Node.js的官方地址:https://nodejs.org/e ...

  3. Redux中的异步操作

    异步操作的另一种方案就是让Action Creator返回一个Promise对象. 我们这边使用  redux-promise  中间件 import { createStore, applyMidd ...

  4. Fragment懒加载预加载

    1. 预加载viewpager.setOffscreenPageLimit(2);,默认是预加载1,可以结合懒加载使用. 如果希望进入viewpager,Fragment只加载一次,再次滑动不需加载( ...

  5. Android应用开发细节点

    1.如果handler是在主线程声明,就属于主线程,handleMessage属于引用handler的那个线程:2.ByteArrayOutputStream/ByteArrayInputStream ...

  6. Linux下Eclipse连接小米手机真机调试

    以前用Ubuntu 12.04可以真机调试,连上手机就可以了,上次看pear os 好看于是下了个玩玩(界面风格像mac 买不起,仿得起),这次想开发安卓发现真机调试不了了...于是乎各种找资料,各种 ...

  7. Can't find bundle for base name messages.AndroidJpsBundle, locale zh_CN

     从http://www.android-studio.org/网站上下载了一个Android Studio 3.0的非安装版本(android-studio-ide-171.4408382-wind ...

  8. Node.js——网站访问一般流程

  9. [分享] IMX6嵌入式开发板linux QT挂载U盘及TF卡

    本文转自迅为开发板:http://www.topeetboard.com 开发平台:iMX6开发板 linux QT 系统下挂载 u 盘如下图所示,qt 启动之后,在超级终端中使用命令“mknod / ...

  10. (转)淘淘商城系列——dubbo监控中心

    http://blog.csdn.net/yerenyuan_pku/article/details/72777623 之前我们就已学过了dubbo,想必大家对dubbo的架构有所了解,dubbo的架 ...