[Luogu2617]Dynamic Ranking
题面戳这
类似算法总结
1、静态整体Kth
滑稽吧...sort一遍就好了。
时间复杂度\(O(nlogn)\) 空间复杂度\(O(n)\)
2、动态整体Kth
离散化后开一棵权值线段树,每个位置的值表示这个位置对应的那个数(离散化后的)有多少个,向上维护和;
查询时先查询左子树和sum,比较k和sum的大小:若k<=sum则说明第k小数在左子树中,递归查询左子树;
否则,这个数对应的就是右子树中第k-sum小的数,k-=sum,递归查询右子树。
时间复杂度\(O(nlogn)\) 空间复杂度\(O(n)\)
3、静态区间Kth
对每个点以其前缀开一棵权值线段树,那么任意一段区间均可以表示成为两棵权值线段树作差,即R位置的线段树减去L-1位置上的线段树
每个点开一棵线段树空间复杂度\(O(n^2)\),MLE,考虑到后一个位置相比于前一个位置的更改只有\(logn\)个节点,所以使用主席树
时间复杂度\(O(nlogn)\) 空间复杂度\(O(nlogn)\)
4、动态区间Kth(就是本题辣)
还是要想办法维护前缀和。如果只是同3、的前缀和的话,就要对前缀和进行\(O(nlogn)\)的单次修改,显然TLE。
这里考虑用树状数组维护前缀和。修改时,可以只修改\(logn\)个位置,复杂度\(O(log^2n)\);
查询时,依旧是R位置减去L-1位置,这时候不再是两棵线段树作差,而是log棵线段树与log棵线段树作差;跳的时候,log个节点一起跳到左子树/右子树
时间复杂度\(O(nlog^2n)\) 空间复杂度\(O(nlog^2n)\)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX=10005;
struct segment_tree{int v;int ls,rs;}t[MAX*400];//线段树开nlog^2大小
struct operation{bool b;int l,r,k;int pos,t;}q[MAX];//因为要离散化所以要把所有数据输进来离线搞
int n,m,a[MAX],o[MAX<<1],rt[MAX],len,tot,temp[2][20],cnt[2];
char opt;
void Modify(int &now,int l,int r,int pos,int val)
{
if (!now) now=++tot;
t[now].v+=val;
if (l==r) return;
int mid=l+r>>1;
if (pos<=mid) Modify(t[now].ls,l,mid,pos,val);
else Modify(t[now].rs,mid+1,r,pos,val);
}
void prepare_Modify(int x,int val)
{
int k=lower_bound(o+1,o+len+1,a[x])-o;
for (int i=x;i<=n;i+=i&-i) Modify(rt[i],1,len,k,val);//处理出需要修改哪log棵主席树
}
int Query(int l,int r,int k)
{
if (l==r) return l;
int mid=l+r>>1,sum=0;
for (int i=1;i<=cnt[1];i++) sum+=t[t[temp[1][i]].ls].v;
for (int i=1;i<=cnt[0];i++) sum-=t[t[temp[0][i]].ls].v;
if (k<=sum)
{
for (int i=1;i<=cnt[1];i++) temp[1][i]=t[temp[1][i]].ls;
for (int i=1;i<=cnt[0];i++) temp[0][i]=t[temp[0][i]].ls;
return Query(l,mid,k);
}
else
{
for (int i=1;i<=cnt[1];i++) temp[1][i]=t[temp[1][i]].rs;
for (int i=1;i<=cnt[0];i++) temp[0][i]=t[temp[0][i]].rs;
return Query(mid+1,r,k-sum);
}
}
int prepare_Query(int l,int r,int k)
{
memset(temp,0,sizeof(temp));//同修改,处理出需要进行相减操作的是哪log棵主席树
cnt[0]=cnt[1]=0;
for (int i=r;i;i-=i&-i) temp[1][++cnt[1]]=rt[i];
for (int i=l-1;i;i-=i&-i) temp[0][++cnt[0]]=rt[i];
return Query(1,len,k);
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for (int i=1;i<=n;i++) cin>>a[i],o[++len]=a[i];
for (int i=1;i<=m;i++)
{
cin>>opt;
q[i].b=(opt=='Q');
if (q[i].b) cin>>q[i].l>>q[i].r>>q[i].k;
else cin>>q[i].pos>>q[i].t,o[++len]=q[i].t;
}
sort(o+1,o+len+1);
len=unique(o+1,o+len+1)-o-1;//离散 —— 排序 + 去重
for (int i=1;i<=n;i++) prepare_Modify(i,1);
for (int i=1;i<=m;i++)
{
if (q[i].b) printf("%d\n",o[prepare_Query(q[i].l,q[i].r,q[i].k)]);
else
{
prepare_Modify(q[i].pos,-1);
a[q[i].pos]=q[i].t;
prepare_Modify(q[i].pos,1);
}
}
return 0;
}
[Luogu2617]Dynamic Ranking的更多相关文章
- 【BZOJ1901】【Luogu2617】Dynamic Ranking(主席树,树状数组)
[BZOJ1901][Luogu2617]Dynamic Ranking(主席树,树状数组) 题面 神TM BZOJ权限题 Luogu真良心 题解 如果不考虑修改 很容易的主席树区间第K大 考虑修改 ...
- AC日记——Dynamic Ranking 洛谷 P2617
Dynamic Ranking 思路: 可持久化树状数组: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...
- 洛谷P2617 Dynamic Ranking(主席树,树套树,树状数组)
洛谷题目传送门 YCB巨佬对此题有详细的讲解.%YCB%请点这里 思路分析 不能套用静态主席树的方法了.因为的\(N\)个线段树相互纠缠,一旦改了一个点,整个主席树统统都要改一遍...... 话说我真 ...
- Luogu Dynamic Ranking (带修改的主席树)
题目大意: 网址:https://www.luogu.org/problemnew/show/2617 给定一个序列a[1].a[2].....a[N],完成M个操作,操作有两种: [1]Q i j ...
- [Luogu2617]Dynamic Rankings(整体二分)
Luogu 动态区间第K大的整体二分解法 之前学主席树的时候就做了这道题(明明是树套树不是主席树啊),码量挺大而且调了我一个晚上.换成整体二分我半个小时就写完了而且一A. 写起来就是爽. 其实原理很简 ...
- Bzoj1901 Dynamic Ranking
动态区间第k小 离散化后 那么每个点开一棵线段树(主席树)再套一个树状数组在外面 每次询问区间内的树的个数时 相当于进行了一次树状数组求区间和的操作,只是是把树状数组那个点看做主席树,对log棵主席树 ...
- 【bzoj1901】dynamic ranking(带修改主席树/树套树)
题面地址(权限题) 不用权限题的地址 首先说说怎么搞带修改主席树? 回忆一般的kth问题,我们的主席树求的是前缀和,这样我们在目标区间的左右端点的主席树差分下就能求出kth. 那么我们如何支持修改操作 ...
- 【bzoj1901】dynamic ranking(带修改主席树)
传送门(权限) 传送门(非权限) 花了一晚上总算把代码调好了……才知道待修改主席树怎么操作…… 然而还是一知半解orz…… 先说说我的理解吧 我们一般建主席树的时候都是直接在序列上建的 但是如果有修改 ...
- [luogu2617]Dynamic Rankings
题面在这里 description 动态区间第\(k\)大 data range \[n,m\le 10000,a_i,t\le 1e^9\] solution 前置技能:主席树,静态区间第\(k\) ...
随机推荐
- UEditor工具栏上自定义按钮、图标、事件和右击菜单添加自定义按钮
首先我要说是,举例说的这个版本是1.2以上的,因为一些配置代码转移到了zh-cn.js里,其他没有变化.开门见山直接写:(我自定义的是在线美图功能) 第一步:找到ueditor.config.js文件 ...
- phpstudy 版本切换注意的问题
如果你也在使用phpstudy的话要注意,因为切换版本后,虽然你的phpinfo 但是实际环境用的是系统环境变量 所以你要去改变下环境变量路径,然后重启电脑. 这样你的版本就是你想切换的版本啦!
- Nginx日志分析及脚本编写
在我们日常的运维中,当Nginx服务器正常运行后,我们会经常密切关注Nginx访问日志的相关情况,发现有异常的日志信息需要进行及时处理. 那今天我将跟大家一起来研究和分析Nginx日志,nginx默认 ...
- spark集成hbase与hive数据转换与代码练习
帮一个朋友写个样例,顺便练手啦~一直在做平台的各种事,但是代码后续还要精进啊... import java.util.Date import org.apache.hadoop.hbase.HBase ...
- 图论算法-最小费用最大流模板【EK;Dinic】
图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...
- 换行符\r \n LF
前言:在对照PSR-2规范时,看到文件结尾必须要以Unix LF(linefeed)结尾,不懂查~ 来源于:http://www.cppblog.com/prayer/archive/2009/08/ ...
- 分布式高性能消息处理中心HPMessageCenter
# HPMessageCenter 高性能消息分发中心.用户只需写好restful接口,在portal里面配置消息的处理地址,消息消费者就会自动访问相关接口,完成消息任务. ### 部署说明 **创建 ...
- Linux常用命令(精选)
chmod -R 777 文件夹名 // -R表示递归给文件及文件夹内文件更改权限,r(4),w(2),x(1),chmod -a+rwx / chmod -u+w -g+r -o +x ...
- JavaScript 一个进行枚举选择的jquery插件(仿easyui风格)
某次做项目要实现一个功能: 按星期选择一个连续的时间范围 比如:周一到周五,周六到周日 或 周六到周三 聪明的朋友马上想出办法:用两个选项为周一到周日的下拉列表实现,对 那样可以,但是我觉得不够友好, ...
- java线程间通信1--简单实例
线程通信 一.线程间通信的条件 1.两个以上的线程访问同一块内存 2.线程同步,关键字 synchronized 二.线程间通信主要涉及的方法 wait(); ----> 用于阻塞进程 noti ...