题面在这里

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队列之理论篇

    定义: 特殊的线性表.       特点: 1.先进先出:连结性. 2.作为一种特殊性的表,主要是在表前端进行删除操作,我们称删除的端为对头(front):只能在表的后端进行插入操作,我们称之为称插入 ...

  2. 自定义控件,继承自 ListView

    public class MyListView extends ListView { /** * 如果在xml中创建并设置了style,就会调用三个参数的. * * @param context * ...

  3. 腾讯招聘网数据爬取存入mongodb

    #!/user/bin/env python3 # -*- coding: utf-8 -*- import requests from lxml import etree from math imp ...

  4. Scrapy核心组件

    • 引擎(Scrapy)用来处理整个系统的数据流处理, 触发事务(框架核心) • 调度器(Scheduler)用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个UR ...

  5. jenkins邮件发送jmeter接口测试报告

    在Jenkins中配置实现邮件通知,Jenkins提供了两种方式的配置. 一种是Jenkins内置默认的邮件通知,但是它本身有很多局限性,比如它的邮件通知无法提供详细的邮件内容.无法定义发送邮件的格式 ...

  6. (数据科学学习手札12)K-means聚类实战(基于R)

    上一篇我们详细介绍了普通的K-means聚类法在Python和R中各自的实现方法,本篇便以实际工作中遇到的数据集为例进行实战说明. 数据说明: 本次实战样本数据集来自浪潮集团提供的美团的商家信息,因涉 ...

  7. Spring 框架控制器类方法可用的参数与返回类型

    参数类型 Spring 有内建的 HTTP 消息转换器用于部分简单类型之间的转换 标准 Servlet 类型:HttpServletRequest, HttpServletResponse, Http ...

  8. maven之package与install的区别

    mvn clean package 先看命令的执行过程 mvn clean install 同样先看执行过程 mvn clean package依次执行了clean.resources.compile ...

  9. 记一次艰难的CTP调试

    一个atmel,mxt540e的CTP触摸屏. 中断配置为下降沿,输入上拉. 总是只能触发一次中断,中断脚就一直低电平,无法拉高.这只是表面现象   不停找底层I2C驱动,改代码,没用.要靠波形来说话 ...

  10. 对工具的反思 & deadlines与致歉

    人和动物最大的区别就是使用工具的水平. 有些人只凭着对工具的熟练掌握便成了牛人. 工具,到底应该以何种态度去看待? 在我小的时候,工具仅仅是指树枝.线.粉笔,可以让自己有更多游戏可玩:上学之后,便又有 ...