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# PropertyInfo(官网)

    using System; using System.Reflection; class Module1 { public static void Main() { // This variable ...

  2. 定时清除 /var/log/massage 下的信息脚本文件

    定时清除 /var/log/massage 下的信息脚本 #!/bin/sh #Date: 0:07 #Author: Xiaodong #Mail: 990974238@qq.com #Puncti ...

  3. Android开发学习——Volley框架

    转载至: http://blog.csdn.net/guolin_blog/article/details/17482095 一些概念性的东西 大家进入上边链接理解,我贴一下 具体的实现代码: pub ...

  4. 【Mybatis】环境搭建

    SqlMapConfig.xml(MyBatis配置文件) <?xml version="1.0" encoding="UTF-8" ?> < ...

  5. hihocoder offer收割编程练习赛12 D 寻找最大值

    思路: 可能数据太水了,随便乱搞就过了. 实现: #include <iostream> #include <cstdio> #include <algorithm> ...

  6. 学习笔记 第十四章 使用CSS3动画

    第14章   使用CSS3动画 [学习重点] 设计2D动画 设计3D动画 设计过渡动画 设计帧动画 能够使用CSS3动画功能设计页面特效样式 14.1  设计2D动画 CSS2D Transform表 ...

  7. 12 DOM操作应用

    1.创建子元素oLi=document.creatElement('li') 2.将元素附给父级元素oUl.appendChild(oLi) 3.将元素插入到父级元素里的第一位子元素之前oUl.ins ...

  8. Android组件化开发(注意事项)

    1.Manifest合并 在Android studio编译项目时,无论你使用了几个Module都会把所有Manifest最终合并成一个,需要我们注意的是application标签下这个几个属性引用的 ...

  9. Objective - c Chapter 1 -2 Hello world

    Objective - c   Chapter 1  Hello world 1.1 1.2.On the Welcome screen, click "Create a new Xcode ...

  10. IIS ARR(Application Request Route)与反向代理(Reverse Proxy)

    为何要用反向代理? 这里说说我的场景, 我在服务器上假设了SVN(Visual SVN)用的端口是:8080, 而我想通过输入svn.niusys.com就可以访问我的SVN服务器,也就是要通过80端 ...