题面在这里

description

动态区间第\(k\)大

data range

\[n,m\le 10000,a_i,t\le 1e^9
\]

solution

前置技能:主席树,静态区间第\(k\)大

注意到主席树的区间维护是通过前缀和来实现的,

修改时需要对所有前缀进行修改,一次复杂度是\(O(nlogn)\),显然会\(TLE\)

树套树(树状数组套线段树???)

于是我们想到把主席树的前缀和维护改成树状数组维护

这样树状数组的每一个节点都代表的是一些权值线段树的前缀和

修改

对于树状数组上要修改的每一棵权值线段树进行修改(需要线段树动态开点),

每次加\(lowbit\)后直接在对应的权值线段树上删原点+插新点即可

需要修改\(O(logn)\)棵权值线段树,时间复杂度为\(O(log^2n)\)

查询

这里我们通过树状数组知道了区间\([l,r]\)的整棵权值线段树

在权值线段树上进行二分;

注意前缀\([1,l]\)和前缀\([1,r]\)在树套树上对应的权值线段树的数量可能不同,

于是我们需要在递归的同时保存这\(O(logn)\)个节点的位置

需要查询\(O(logn)\)棵权值线段树,时间复杂度为\(O(log^2n)\)

那么这道题目我们就很开心地做完啦

code

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define lowbit(x) (x&-x)
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e8;
const int N=20010;
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
} il void file(){
freopen(".in","r",stdin);
freopen(".out","w",stdout);
} int n,m,len,a[N],o[N],cnt[2][N],rt[N],tot;char c;
struct query{int opt;int l,r,k;int p,t;}Q[N];
struct node{int v,ls,rs;}t[N*400];
#define mid ((l+r)>>1) ll query(int l,int r,int k){
if(l==r)return l;RG int sum=0;
for(RG int i=1;i<=cnt[0][0];i++){
sum-=t[t[cnt[0][i]].ls].v;
}
for(RG int i=1;i<=cnt[1][0];i++){
sum+=t[t[cnt[1][i]].ls].v;
}
if(k<=sum){
for(RG int i=1;i<=cnt[0][0];i++)
cnt[0][i]=t[cnt[0][i]].ls;
for(RG int i=1;i<=cnt[1][0];i++)
cnt[1][i]=t[cnt[1][i]].ls;
return query(l,mid,k);
}
else{
for(RG int i=1;i<=cnt[0][0];i++)
cnt[0][i]=t[cnt[0][i]].rs;
for(RG int i=1;i<=cnt[1][0];i++)
cnt[1][i]=t[cnt[1][i]].rs;
return query(mid+1,r,k-sum);
}
}
il void query_tree(int l,int r,int k){
cnt[0][0]=cnt[1][0]=0;
for(RG int i=l-1;i;i-=lowbit(i))
cnt[0][++cnt[0][0]]=rt[i];
for(RG int i=r;i;i-=lowbit(i))
cnt[1][++cnt[1][0]]=rt[i];
printf("%d\n",o[query(1,len,k)]);
} void modify(int &now,int l,int r,int p,int val){
if(!now)now=++tot;t[now].v+=val;if(l==r)return;
if(p<=mid)modify(t[now].ls,l,mid,p,val);
else modify(t[now].rs,mid+1,r,p,val);
}
il void modify_tree(int p,int val){
RG int x=lower_bound(o+1,o+len+1,a[p])-o;
for(RG int i=p;i<=n;i+=lowbit(i)){
modify(rt[i],1,len,x,val);
}
} int main()
{
len=n=read();m=read();
for(RG int i=1;i<=n;i++)o[i]=a[i]=read();
for(RG int i=1;i<=m;i++){
c=0;while(c!='Q'&&c!='C')c=getchar();
Q[i].opt=(c=='Q');
if(c=='Q'){
Q[i].l=read();Q[i].r=read();Q[i].k=read();
}
else {Q[i].p=read();Q[i].t=read();o[++len]=Q[i].t;}
}
sort(o+1,o+len+1);len=unique(o+1,o+len+1)-o-1; for(RG int i=1;i<=n;i++)modify_tree(i,1);
for(RG int i=1;i<=m;i++)
if(!Q[i].opt){
modify_tree(Q[i].p,-1);
a[Q[i].p]=Q[i].t;
modify_tree(Q[i].p,1);
}
else{query_tree(Q[i].l,Q[i].r,Q[i].k);}
return 0;
}

[luogu2617]Dynamic Rankings的更多相关文章

  1. [Luogu2617]Dynamic Rankings(整体二分)

    Luogu 动态区间第K大的整体二分解法 之前学主席树的时候就做了这道题(明明是树套树不是主席树啊),码量挺大而且调了我一个晚上.换成整体二分我半个小时就写完了而且一A. 写起来就是爽. 其实原理很简 ...

  2. [BZOJ1901][luogu2617]Dynamic Rankings(树状数组+主席树)

    题面 单点修改,区间求第k大 分析 首先,这道题卡权值线段树套treap的做法,所以只能用主席树做 对于静态的查询,root[i]对应的主席树的区间[l,r]保存的是a[1]~a[i]有多少个值落在区 ...

  3. 「luogu2617」Dynamic Rankings

    「luogu2617」Dynamic Rankings 传送门 树套树直接上树状数组套主席树,常数很大就是了. 树套树参考代码: /*-------------------------------- ...

  4. BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7143  Solved: 2968[Su ...

  5. [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  6. [BZOJ1901]Zju2112 Dynamic Rankings

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

  7. ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)

    题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...

  8. BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Submit: 6058 Solved: 2521 [Su ...

  9. ZOJ 2112 Dynamic Rankings(主席树の动态kth)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 The Company Dynamic Rankings ...

随机推荐

  1. Asp.Net Core 生成图形验证码

    前几天有朋友问我怎么生成图片验证码,话不多说直接上代码. 支持.NET CORE开源.助力.NET Core社区发展. using System; using System.IO; using Sys ...

  2. MySQL数据操作(DML)

    表结构准备: mysql> CREATE TABLE student( -> sid INT PRIMARY KEY AUTO_INCREMENT, ), -> age INT, ) ...

  3. 2.1 进程控制之fork创建子进程

    fork()函数 目标:熟悉fork创建一个和多个子进程子线程 函数原型:pid_t fork(void); 返回值:成功返回:① 父进程返回子进程的ID(非负) ②子进程返回 0 : 失败返回-1. ...

  4. clear()、sync()、ignore()

    #include <iostream> using namespace std; int main() { int a; cin>>a; cout<<cin.rds ...

  5. (数据科学学习手札08)系统聚类法的Python源码实现(与Python,R自带方法进行比较)

    聚类分析是数据挖掘方法中应用非常广泛的一项,而聚类分析根据其大体方法的不同又分为系统聚类和快速聚类,其中系统聚类的优点是可以很直观的得到聚类数不同时具体类中包括了哪些样本,而Python和R中都有直接 ...

  6. 牛客网暑期ACM多校训练营(第四场) F

    参考:http://www.cnblogs.com/Jadon97/p/9383027.html #include <iostream> #include <cstdio> # ...

  7. DDL失败案例

    问题描述 今天对线上某个业务的大表120G进行重建表操作时遇到报错,该表有个比较显著的特征是*写入量比较大,每天写入加更新的频率在数千万级别.大致的环境 1 版本:Percona 5.6.24 2 操 ...

  8. ORB-SLAM (四)tracking单目初始化

    单目初始化以及通过三角化恢复出地图点 单目的初始化有专门的初始化器,只有连续的两帧特征点均>100个才能够成功构建初始化器. ); 若成功获取满足特征点匹配条件的连续两帧,并行计算分解基础矩阵和 ...

  9. 『AngularJS』ngShow

    原文 描述 ngShow指令显示或隐藏给定的基于标明ngShow属性的HTML元素.元素的显示或隐藏通过在元素上移除或添加ng-hide CSS类属性.".ng-hide"CSS类 ...

  10. Daily Scrum02 12.02

    今天是黑色星期一,虽然大家最近被各种大作业压得身心疲惫,但是团队的凝聚力战胜了一切不快. 看看同志们今天的战绩,是不是又有一种充实感油然而生呢??? By Ryan Mao who? Today? T ...