学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同…
那么原理也比较易懂:
建造一棵线段树(权值线段树),维护的信息是序列中每个数的出现次数,静态查询第K极值,只需要从根做二分,然后向下转左右子树,找到叶子节点即可…(由于线段树的性质,这个查找的复杂度是log级..)
那么动态的第K极值呢..
需要用上树状数组,这时树状数组维护的其实就是一串主席树了,不过这样处理,会MLE,但是应用可持久化原理,每次修改,对于线段树来说,只是修改了一个叶子点到根的路径,其余的路径都是不变的,所以每次只需要保存一条路径即可咯,但是如何找到那样的数 呢….此处应用前缀和操作,r和l-1的差值即为l~r的值,所以用同样原理,应用树状数组维护即可..代码量会降低..
动态维护模板(ZOJ2112)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 60010
#define M 2500010
int n,q,m,tot;
int a[MAXN],t[MAXN];
int T[MAXN],lc[M],rc[M],c[M];
int S[MAXN];
struct data{
int kind;int l,r,k;
}query[10010];
void init_hash(int num)
{
sort(t,t+num);
m=unique(t,t+num)-t;
}
int hash(int x)
{
return lower_bound(t,t+m,x)-t;
}
int build(int l,int r)
{
int root=tot++;
c[root]=0;
if (l!=r)
{
int mid=(l+r)/2;
lc[root]=build(l,mid);
rc[root]=build(mid+1,r);
}
return root;
}
int insert(int root,int pos,int val)
{
int newroot=tot++,tmp=newroot;
int l=0,r=m-1;
c[newroot]=c[root]+val;
while (l<r)
{
int mid=(l+r)>>1;
if (pos<=mid)
{
lc[newroot]=tot++; rc[newroot]=rc[root];
newroot=lc[newroot]; root=lc[root];
r=mid;
}
else
{
rc[newroot]=tot++; lc[newroot]=lc[root];
newroot=rc[newroot]; root=rc[root];
l=mid+1;
}
c[newroot]=c[root]+val;
}
return tmp;
}
int lowbit(int x){return x&(-x);}
int use[MAXN];
void add(int x,int pos,int val)
{
while (x<=n)
{
S[x]=insert(S[x],pos,val);
x+=lowbit(x);
}
}
int sum(int x)
{
int re=0;
while (x>0)
{
re+=c[lc[use[x]]];
x-=lowbit(x);
}
return re;
}
int Query(int L,int R,int k)
{
int l_root=T[L-1];
int r_root=T[R];
int l=0,r=m-1;
for (int i=L-1; i; i-=lowbit(i)) use[i]=S[i];
for (int i=R; i; i-=lowbit(i)) use[i]=S[i];
while (l<r)
{
int mid=(l+r)>>1;
int tmp=sum(R)-sum(L-1)+c[lc[r_root]]-c[lc[l_root]];
if (tmp>=k)
{
r=mid;
for (int i=L-1; i; i-=lowbit(i)) use[i]=lc[use[i]];
for (int i=R; i; i-=lowbit(i)) use[i]=lc[use[i]];
l_root=lc[l_root];
r_root=lc[r_root];
}
else
{
l=mid+1;k-=tmp;
for (int i=L-1; i; i-=lowbit(i)) use[i]=rc[use[i]];
for (int i=R; i; i-=lowbit(i)) use[i]=rc[use[i]];
l_root=rc[l_root];
r_root=rc[r_root];
}
}
return l;
}
void Modify(int x,int p,int d)
{
while (x<=n)
{
S[x]=insert(S[x],p,d);
x+=lowbit(x);
}
}
int main()
{
int test;
scanf("%d",&test);
while (test--)
{
scanf("%d%d",&n,&q);
tot=0;m=0;
for (int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
t[m++]=a[i];
}
char opt[10];
for (int i=0; i<q; i++)
{
scanf("%s",opt);
if (opt[0]=='Q')
{
query[i].kind=0;
scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k);
}
else
{
query[i].kind=1;
scanf("%d%d",&query[i].l,&query[i].r);
t[m++]=query[i].r;
}
}
init_hash(m);
T[0]=build(0,m-1);
for (int i=1; i<=n; i++)
T[i]=insert(T[i-1],hash(a[i]),1);
for (int i=1; i<=n; i++)
S[i]=T[0];
for (int i=0; i<q; i++)
{
if (query[i].kind==0)
printf("%d\n",t[Query(query[i].l,query[i].r,query[i].k)]);
else
{
Modify(query[i].l,hash(a[query[i].l]),-1);
Modify(query[i].l,hash(query[i].r),1);
a[query[i].l]=query[i].r;
}
}
}
return 0;
}
学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))的更多相关文章
- [COGS257]动态排名系统 树状数组套主席树
257. 动态排名系统 时间限制:5 s 内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- BZOJ 2141 排队(树状数组套主席树)
解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...
- Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)
E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...
- BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树
BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...
- ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解
题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...
- 【Luogu】P2617Dynamic Ranking(树状数组套主席树)
题目链接 树状数组套主席树有点难懂qwq 不好理解 树状数组套主席树的直观理解应该是:树状数组的每一个节点是一棵主席树. 普通区间修改我们是创建1个线段树,树状数组套主席树的时候我们就创建log个线段 ...
- [BZOJ3932] [CQOI2015]任务查询系统(主席树 || 树状数组 套 主席树 + 差分 + 离散化)
传送门 看到这个题有个很暴力的想法, 可以每一个时间点都建一颗主席树,主席树上叶子节点 i 表示优先级为 i 的任务有多少个. 当 x 到 y 有个优先级为 k 的任务时,循环 x 到 y 的每个点, ...
- LUOGU P2617 Dynamic Rankings(树状数组套主席树)
传送门 解题思路 动态区间第\(k\)大,树状数组套主席树模板.树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和.然后询问的时候\(log\)个点一起做前缀和,一起移动.时空复杂度\(O ...
- bzoj1901--树状数组套主席树
树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...
随机推荐
- Unity-WIKI 之 DebugLine
脚本功能 在Unity中要使用画线功能,需要添加LineRenderer 组件,或打开Gizmos功能,下面这个组件为开发带来了方便 功能预览 搭建步骤 1.创建“Plugins” 文件夹 2.在“P ...
- flex4 s:Datagrid <s:typicalItem
<s:DataGird <s:typicalItem 这个标签相信大家很陌生吧, 我也是今天准备讲的时候才看到,估计是 flex4.5.1 新加东西,果然摸索 了下,这个标签作用也蛮好用的 ...
- JMeter学习(三十二)属性和变量
一.Jmeter中的属性: 1.JMeter属性统一定义在jmeter.properties文件中,我们可以在该文件中添加自定义的属性 2.JMeter属性在测试脚本的任何地方都是可见的(全局),通常 ...
- git详细教程
Table of Contents 1 Git详细教程 1.1 Git简介 1.1.1 Git是何方神圣? 1.1.2 重要的术语 1.1.3 索引 1.2 Git安装 1.3 Git配置 1.3.1 ...
- php基础24:数组range
<?php $numbers = range(1, 10); echo "<pre>"; var_dump($numbers); echo "</ ...
- SgmlReader使用方法
HtmlAgilityPack是一个开源的html解析器,底层是通过将html格式转成标准的xml格式文件来实现的(使用dot net里的XPathDocument等xml相关类),可以从这里下载:h ...
- java.sql.SQLException: 对只转发结果集的无效操作: last
出错代码如下:static String u = "user";static String p = "psw";static String url = &quo ...
- Android使用service后台更新计划任务
Service是Android的四大组件之一,这里就不再过多的去描述,下面主要实现启动应用时候利用service后台执行计划任务,退出应用后,关闭service,只存在整个应用的周期中. 首先使用se ...
- Linux及安全——程序破解
Linux及安全——程序破解 由于我的Ubuntu的vi有故障,所以用kaili做. 运行原程序 1.反汇编代码,查看 objdump -d login 2.修改代码 vi login 转换为16进制 ...
- iOS开发系列--音频播放(音效和音乐)播放本地的
音频 在iOS中音频播放从形式上可以分为音效播放和音乐播放.前者主要指的是一些短音频播放,通常作为 点缀音频,对于这类音频不需要进行进度.循环等控制.后者指的是一些较长的音频,通常是主音频,对于这些音 ...