洛谷题目传送门

YCB巨佬对此题有详细的讲解。%YCB%请点这里

思路分析

不能套用静态主席树的方法了。因为的\(N\)个线段树相互纠缠,一旦改了一个点,整个主席树统统都要改一遍。。。。。。

话说我真的快要忘了有一种数据结构,能支持单点修改,区间查询,更重要的是,常数优秀的它专门用来高效维护前缀和!!它就是——

!树状数组!

之前静态主席树要保存的每个线段树\([1,i]\),不也是一个庞大的前缀吗?于是,把树状数组套在线段树上,构成支持动态修改的主席树。每个树状数组的节点即为一个线段树的根节点。

举个栗子,维护一个长度为\(5\)的序列,树状数组实际会长成这样——

于是就利用树状数组来维护前缀和了。首先是修改(设修改元素位置为\(i\))。从下标为\(i\)的树状数组节点开始,每次都往后跳(+=lowbit(i)),所有跳到的线段树都改一遍,原值对应区间-1,新值对应区间+1。一共要改\(log\)棵树。

然后是查询。先把\(l-1\)和\(r\)都往前跳(-=lowbit(i)),每次跳到的都记下来。求当前\(size\)的时候,用记下来的\(log\)棵由\(r\)得到的节点左儿子的\(size\)和(就代表\([1,r]\)的\(size\))减去\(log\)棵由\(l-1\)得到的节点左儿子的\(size\)和(就代表\([1,l-1]\)的\(size\))就是\([l,r]\)的\(size\)。往左/右儿子跳的时候也是\(log\)个节点一起跳。

其实还有一个问题,一开始本蒟蒻想不通,就是\(N\)棵线段树已经无法共用内存了,那空间复杂度不会是\(O(N^2\log N)\)吗?

其实没必要担心的。。。。。。

只考虑修改操作,每次有\(log\)棵线段树被挑出来,每个线段树只修改\(log\)个节点,因此程序一趟跑下来,仅有\(N\log^2N\)个节点被访问过,我们只需要动态开点就好了。

下面贴代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define R register int
const int N=10009,M=4000009;//M:开Nlog²的空间
bool op[N];
int L,P,n,a[N],b[N],c[N],d[N],g[N<<1];
int rt[N],lc[M],rc[M],s[M];
int pl,pr,reql[20],reqr[20];
#define G ch=getchar()
#define GO G;while(ch<'-')G
#define in(z) GO;z=ch&15;G;while(ch>'-')z*=10,z+=ch&15,G
inline void update(R p,R v)//修改
{
R k=lower_bound(g+1,g+L+1,a[p])-g;//先找到离散化后对应值
for(R i=p;i<=n;i+=i&-i)
{
R*t=&rt[i],l=1,r=L,m;
while(l!=r)
{
if(!*t)*t=++P;//动态分配空间
s[*t]+=v;
m=(l+r)>>1;
if(k<=m)r=m,t=&lc[*t];
else l=m+1,t=&rc[*t];
}
if(!*t)*t=++P;
s[*t]+=v;
}
}
inline int ask(R l,R r,R k)
{
R i,m,sum;
pl=pr=0;
for(i=l-1;i;i-=i&-i)
reql[++pl]=rt[i];
for(i=r;i;i-=i&-i)
reqr[++pr]=rt[i];//需要查询的log个线段树全记下来
l=1;r=L;
while(l!=r)
{
m=(l+r)>>1;sum=0;
for(i=1;i<=pr;++i)sum+=s[lc[reqr[i]]];
for(i=1;i<=pl;++i)sum-=s[lc[reql[i]]];//一起加一起减
if(k<=sum)
{
for(i=1;i<=pl;++i)reql[i]=lc[reql[i]];
for(i=1;i<=pr;++i)reqr[i]=lc[reqr[i]];
r=m;
}//一起向同一边儿子跳
else
{
for(i=1;i<=pl;++i)reql[i]=rc[reql[i]];
for(i=1;i<=pr;++i)reqr[i]=rc[reqr[i]];
l=m+1;k-=sum;
}
}
return g[l];
}
int main()
{
register char ch;
R m,i;
in(n);in(m);L=n;
for(i=1;i<=n;++i){in(a[i]);}
memcpy(g,a,(n+1)<<2);
for(i=1;i<=m;++i)
{
GO;op[i]=ch=='Q';
in(b[i]);in(c[i]);
if(op[i]){in(d[i]);}
else g[++L]=c[i];//变成动态的了,离散化时后面需要修改的值也要考虑进去,所以先把所有操作保存起来
}
sort(g+1,g+L+1);
L=unique(g+1,g+L+1)-g-1;//离散化
for(i=1;i<=n;++i)update(i,1);//一开始还是每个点都要更新一遍
for(i=1;i<=m;++i)
{
if(op[i])printf("%d\n",ask(b[i],c[i],d[i]));
else
{
update(b[i],-1);//注意被替代的以前那个值要减掉
a[b[i]]=c[i];
update(b[i],1);
}
}
return 0;
}

洛谷P2617 Dynamic Ranking(主席树,树套树,树状数组)的更多相关文章

  1. 洛谷P2617 Dynamic Rankings (主席树)

    洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...

  2. 洛谷P2617 Dynamic Rankings 主席树 单点修改 区间查询第 K 大

    我们将线段树套在树状数组上,查询前预处理出所有要一起移动的节点编号,并在查询过程中一起将这些节点移到左右子树上. Code: #include<cstdio> #include<cs ...

  3. 洛谷 P2617 Dynamic Ranking

    题目描述 给定一个含有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≤ ...

  4. 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)

    P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...

  5. 洛谷 P2617 Dynamic Rankings || ZOJ - 2112

    写的让人看不懂,仅留作笔记 静态主席树,相当于前缀和套(可持久化方法构建的)值域线段树. 建树方法:记录前缀和的各位置的线段树的root.先建一个"第0棵线段树",是完整的(不需要 ...

  6. 洛谷P2617 Dynamic Rankings

    带修主席树模板题 主席树的单点修改就是把前缀和(大概)的形式改成用树状数组维护,每个树状数组的元素都套了一个主席树(相当于每个数组的元素root[i]都是主席树,且这个主席树维护了(i - lowbi ...

  7. 洛谷 P2617 Dynamic Rankings 解题报告

    P2617 Dynamic Rankings 题目描述 给定一个含有\(n\)个数的序列\(a[1],a[2],a[3],\dots,a[n]\),程序必须回答这样的询问:对于给定的\(i,j,k\) ...

  8. 洛谷$P2617\ Dynamic\ Rankings$ 整体二分

    正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...

  9. 【小技巧】树剖套线段树优化建图如何做到 O(nlogn)

    前提:用树剖套线段树优化树链连边.例题:bzoj4699 我们说树剖的时间复杂度是 $O(n\times log(n))$,是因为访问一条链时需要经过 $log(n)$ 级别条重链,对于每条重链还需要 ...

随机推荐

  1. mongodb window安装配置

    下载mongodb安装包 1. https://www.mongodb.org/dl/win32/x86_64-2008plus-ssl?_ga=2.233271640.711265466.15193 ...

  2. LeetCode - 520. Detect Capital

    Given a word, you need to judge whether the usage of capitals in it is right or not. We define the u ...

  3. ionic2+Angular web端 实现微信分享以及如何跳转回分享出去的页面

    微信分享,首先参考微信JS-SDK开发文档. step1:在启动文件index.html中引入微信js文件: <script src="http://res.wx.qq.com/ope ...

  4. 【Tools】ubuntu虚拟机Vmware Tools 安装记录

    1.下载VmwareTools 链接: https://pan.baidu.com/s/1c4baji4 密码: h3si 2.终端打开下载文件位置 cd /home/ubuntu/Downloads ...

  5. 将Word表格中单元格中的文字替换成对应的图片

    示例 原文件结构: 替换后文档结构: 软件截图: 代码: using System;using System.Collections.Generic;using System.ComponentMod ...

  6. Js比较对Object类型进行排序

    <script> var data=[{name:"121",age:"18",year:"2018"},{name:" ...

  7. java1环境与简介

    java1环境与简介   Ⅰ 个人简介 陈鹏 联系方式:15828682774 2012 年至今,从事软件开发 5 年. 1 年新加坡海外工作经历. 先后在民企.外企.创业公司做过开发. 熟悉 JAV ...

  8. 初学Python(第一课)

    今天整理一下关于Python初学者的基础知识部分的第一课,因为之前学习过C,所以过于基础的知识就不详细记录了. Python相对于C\C++来说,在语法方面已经很简单了:甚至对于JavaScript也 ...

  9. 关于HTTP,你知道哪些?

    HTTP简介 HTTP 的全称是 Hypertext Transfer Protocol,超文本传输协议 规定客户端和服务器之间的数据传输格式 让客户端和服务器能有效地进行数据沟通 HTTP 协议是网 ...

  10. ElasticSearch 5.0.0 集群安装部署文档

    1.  搭建环境 3台物理机 操作系统 centos7 es1   192.168.31.141   4g内存   2核 es2   192.168.31.142   4g内存   2核 es3    ...