函数式线段树..资瓷 区间第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极值(树状数组套主席树))的更多相关文章

  1. [COGS257]动态排名系统 树状数组套主席树

    257. 动态排名系统 时间限制:5 s   内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...

  2. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  3. BZOJ 2141 排队(树状数组套主席树)

    解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...

  4. 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 ...

  5. BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树

    BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...

  6. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  7. 【Luogu】P2617Dynamic Ranking(树状数组套主席树)

    题目链接 树状数组套主席树有点难懂qwq 不好理解 树状数组套主席树的直观理解应该是:树状数组的每一个节点是一棵主席树. 普通区间修改我们是创建1个线段树,树状数组套主席树的时候我们就创建log个线段 ...

  8. [BZOJ3932] [CQOI2015]任务查询系统(主席树 || 树状数组 套 主席树 + 差分 + 离散化)

    传送门 看到这个题有个很暴力的想法, 可以每一个时间点都建一颗主席树,主席树上叶子节点 i 表示优先级为 i 的任务有多少个. 当 x 到 y 有个优先级为 k 的任务时,循环 x 到 y 的每个点, ...

  9. LUOGU P2617 Dynamic Rankings(树状数组套主席树)

    传送门 解题思路 动态区间第\(k\)大,树状数组套主席树模板.树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和.然后询问的时候\(log\)个点一起做前缀和,一起移动.时空复杂度\(O ...

  10. bzoj1901--树状数组套主席树

    树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...

随机推荐

  1. HOJ 1640 Mobile Phone

    题意:有一个n*n的矩阵,op==1时,在(x,y)增加值z,op==2时,求以(x1,y1)和(x2,y2)构成的矩阵的和. 思路:二维线段树. 代码: #include<stdio.h> ...

  2. Spring 一二事(1)

    简单介绍一下spring,一方面带新手入入门,一方面自己也重温一下第一个小工厂先暂时不用maven,下一个会用maven来来配置 jar包只需要一个,spring版本为2.5(暂时为2.5,后续更新, ...

  3. uGUI练习(九) Toggle Button

    练习目标 练习单选框,多选框 Toggle Group:Toggle容器 Toggle:单一的选项 练习步骤 1.创建一个Panel,命名TogglePanel,添加Toggle Group组件,可以 ...

  4. 常用的adb命令

    在平时的工作中,会经常用到adb命令,在这里稍微整理了一下. 一.概要 1.什么是adb? adb全称为Android Debug Bridge,就是起到调试桥的作用.顾名思义,adb就是一个debu ...

  5. 创建Java Web监听器

    之前从Java web一路学习过来,一直没有学习过Servlet容器类的一些高级用法,因为学完简单的JSP以及Servlet编写之后就开始了Spring的学习 对web应用的一些常用变量进行 appl ...

  6. 多线程BackgroundWorker

    链接:http://www.cnblogs.com/yiyisawa/archive/2008/11/24/1339826.html 周六闲来无事,学习了多线程BackgroundWorker,以此记 ...

  7. uart串口的调试学习

    用FPGA设计了数据接收和发送模块,FIFO模块,此处FIFO调用的是Show-ahead模式,在下一篇博客中将会分析这个问题. 用串口调试工具发送数据,数据接收模块将接收到的串行数据转换为并行数据( ...

  8. linux测速软件speedtest-cli

    linux测速软件: https://github.com/sivel/speedtest-cli 以下是我在gentoo上测的

  9. Jquery easyui tree的使用

    这个ui用的一切都是json数据.树也是如此! 后台需要返回与格式匹配的json数据才能正确加载树. 页面定义一个ui: <ul id="messageInfoAddTree" ...

  10. 模拟alert和confirm

    啥也不说,先上图,有图有真相 :) 现在绝大多数网站都不用自带的alert和confirm了,因为界面太生硬了.因此这个插件就这样产生了... 来看插件的实现代码吧: (function () { $ ...