题面在这里

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. 实现php Curl 调用不同项目中方法

    之前为了实现跨项目调用方法,遇到的一些问题和解决方法总结. 话不多说,直接复制代码先跑了再说! jq代码. $.ajax({ type: "post", dataType: &qu ...

  2. vue $set修改数组

    看了别人写的,自己简单写一下自己的理解. 因为 JavaScript 的限制,Vue.js 不能检测到下面数组变化,所以,想要正常是不能通过操作数组来渲染dom的,解决的方法是通过set方法, 在组件 ...

  3. python 方法解析顺序 mro

    一.概要: mor(Method Resolution Order),即方法解析顺序,是python中用于处理二义性问题的算法 二义性: 1.两个基类,A和B都定义了f()方法,c继承A和B那么C调用 ...

  4. php+高德地图webapi 高德jsapi 实现 当前位置与目标位置距离 并按照距离排序(坐标逆转换)

    <script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak='自己 ...

  5. 11个简单实用技巧--Java性能调优

    多数开发人员认为性能优化是个比较复杂的问题,需要大量的经验和知识.是的,这并不没有错.诚然,优化应用程序以获得最好的性能并不是一件容易的事情,但这并不意味着你在没有获得这些经验和知识之前就不能做任何事 ...

  6. 我是一个MySQL小白

    我是一个MySQL小白 第一回早起装扮 “mysql,Oracle,SQL-SERVER你们三个 起床没?”,清晨七点多师父喊道. “师父,我(mysql)哪敢睡觉呀,我还在查询表呢,有客户的密码忘记 ...

  7. Python基础教程学记(1)

    引言 Python是什么?——Python是一种面向对象的解释性高级编程语言,具有动态语义.这句话的要点在于,Python是一种知道如何不妨碍你编写程序的编程语言.它让你能够毫无困难地实现所需的功能, ...

  8. HDU暑假多校第八场G-Card Game

    一.题意 给出N个卡牌,卡牌的正反两面具有两个数字,取值范围为[1,2*n],给出若干个默认正面向上的卡牌,求最小反转多少张卡牌可以使得,每张卡牌朝上的面上都有一个不同的数字,同时满足最小反转次数的反 ...

  9. 9 udp广播

    udp有广播  写信 tcp没有广播·  打电话 #coding=utf-8 import socket, sys dest = ('<broadcast>', 7788) # 创建udp ...

  10. es同步mysql同步-logstash

    1.下载es https://www.elastic.co/downloads/elasticsearch 修改 config 下elasticsearch.yml   ip和端口等配置 2.下载ki ...