洛谷P2617 Dynamic Rankings

题目描述

给定一个含有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≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。

对于每一个询问指令,你必须输出正确的回答。

输入输出格式

输入格式:

第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。

第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t

  • Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。

  • C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。

输出格式:

对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

输入输出样例

输入样例#1:

5 3

3 2 1 4 7

Q 1 4 3

C 2 6

Q 2 5 3

输出样例#1:

3

6

说明

10%的数据中,m,n≤100;

20%的数据中,m,n≤1000;

50%的数据中,m,n≤10000。

对于所有数据,m,n≤100000

请注意常数优化,但写法正常的整体二分和树套树都可以以大约1000ms每个点的时间过。

来源:bzoj1901

本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。

Solution

带修改主席树...

我们都知道静态主席树每颗节点保存当前管理区间的所有权值的出现次数,因为每棵树的形态结构都相同,所以我们可以通过对树进行相加减求得静态区间第k大(小)

但是如果要修改的话,若我们暴力修改的话是需要对前缀和进行\(O(nlogn)\)的单次修改,会T飞

那么我们就需要请擅长管理前缀和的树状数组来处理,而主席树现在只负责维护前缀和的辅助数组,套上树状数组的话,我们就只需要修改\(logn\)的节点,复杂度\(O(log^2n)\)

注意1:与静态主席树不同的是带修改主席树中的每一棵线段树所管理的信息都是独立的,不需要继承上一棵线段树的信息

注意2:不但需要对原数组进行离散,还要把修改之后的值也加进来,不然修改后的值不一定能在离散数组中找得到位置

Code

#include<bits/stdc++.h>
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define rg register
#define mid ((l+r)>>1)
#define in(i) (i=read())
using namespace std; const int N=1e5+10; int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
return ans*=f;
} int n,m,num,tot,cnt1,cnt2;
int a[N],h[N<<1],now[5][N<<8],rt[N<<8]; struct Tree {
int v,l,r;
}t[N<<8]; struct Query{
int op,l,r,k;
}q[N]; int lowbit(int x) {return x&-x;} void update(int &u,int l,int r,int pos,int val) {//不需要继承上一棵线段树的信息,带修改主席树的每一棵线段树管理的信息都是独立的
if(!u) u=++tot; t[u].v+=val;
if(l==r) return;
if(pos<=mid) update(t[u].l,l,mid,pos,val);
else update(t[u].r,mid+1,r,pos,val);
} void modify(int x,int val) {//处理出哪些节点需要修改
int k=lower_bound(h+1,h+1+num,a[x])-h;
for (int i=x;i<=n;i+=lowbit(i)) update(rt[i],1,num,k,val);
} int query(int l,int r,int k,int sum=0) {
if(l==r) return h[l];
for (int i=1;i<=cnt1;i++) sum-=t[t[now[1][i]].l].v;
for (int i=1;i<=cnt2;i++) sum+=t[t[now[2][i]].l].v;
if(k<=sum) {
for (int i=1;i<=cnt1;i++) now[1][i]=t[now[1][i]].l;//如果当前左子树的前缀次数小于等于k,那么答案就在左子树中
for (int i=1;i<=cnt2;i++) now[2][i]=t[now[2][i]].l;
return query(l,mid,k);
}
else {//否则在右子树中
for (int i=1;i<=cnt1;i++) now[1][i]=t[now[1][i]].r;
for (int i=1;i<=cnt2;i++) now[2][i]=t[now[2][i]].r;
return query(mid+1,r,k-sum);
}
} int pre_query(int l,int r,int k) {//处理出哪些节点需要查询
cnt1=cnt2=0, l--;
for (int i=l;i;i-=lowbit(i)) now[1][++cnt1]=rt[i];
for (int i=r;i;i-=lowbit(i)) now[2][++cnt2]=rt[i];
return query(1,num,k);
} int main()
{
in(n), in(m);
for (int i=1;i<=n;i++) in(a[i]),h[++num]=a[i];
for (int i=1;i<=m;i++) {
char s[10]; scanf("%s",s);
if(s[0]=='Q') in(q[i].l), in(q[i].r), in(q[i].k), q[i].op=1;
else in(q[i].l), in(q[i].r), h[++num]=q[i].r, q[i].op=0;
}
sort(h+1,h+1+num), num=unique(h+1,h+1+num)-h-1;
for (int i=1;i<=n;i++) modify(i,1);
for (int i=1;i<=m;i++) {
if(q[i].op==0) {
modify(q[i].l,-1);
a[q[i].l]=q[i].r;
modify(q[i].l,1);
}
else printf("%d\n",pre_query(q[i].l,q[i].r,q[i].k));
}
}

洛谷P2617 Dynamic Rankings (主席树)的更多相关文章

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

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

  2. 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 ...

  3. 洛谷 P2617 Dynamic Rankings 解题报告

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

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

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

  5. 洛谷P2617 Dynamic Rankings

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

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

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

  7. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

  8. 洛谷P2617 Dynamic Ranking(主席树,树套树,树状数组)

    洛谷题目传送门 YCB巨佬对此题有详细的讲解.%YCB%请点这里 思路分析 不能套用静态主席树的方法了.因为的\(N\)个线段树相互纠缠,一旦改了一个点,整个主席树统统都要改一遍...... 话说我真 ...

  9. Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化

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

随机推荐

  1. hive的内置函数和自定义函数

    一.内置函数 1.一般常用函数 .取整函数 round() 当传入第二个参数则为精度 bround() 银行家舍入法:为5时,前一位为偶则舍,奇则进. .向下取整 floor() .向上取整 ceil ...

  2. Spring学习(1):侵入式与非侵入式,轻量级与重量级

    一. 引言 在阅读spring相关资料,都会提到Spring是非侵入式编程模型,轻量级框架,那么就有必要了解下这些概念. 二. 侵入式与非侵入式 非侵入式:使用一个新的技术不会或者基本不改变原有代码结 ...

  3. LeetCode-124.二叉树中的最大路径和

    给定一个非空二叉树,返回其最大路径和. 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列.该路径至少包含一个节点,且不一定经过根节点. 示例 1: 输入: [1,2,3] 1 / \ 2 ...

  4. eos合约案例导读

    为了帮助大家熟悉 EOS 智能合约,EOS 官方提供了一个代币(资产)智能合约 Demo -- eosio.token.eosio.token 智能合约目前还不是特别完善,个别功能还没有完成.但这个示 ...

  5. 如何使用openstack OCL

    本节首先讨论 image 删除操作,然后介绍 OpenStack CLI 的使用方法,最后讨如何 Troubleshoot. Web UI 删除 image admin 登录后,Project -&g ...

  6. 第七次ScrumMeeting博客

    第七次ScrumMeeting博客 本次会议于11月1日(三)22时整在3公寓725房间召开,持续15分钟. 与会人员:刘畅.辛德泰.窦鑫泽.张安澜.赵奕.方科栋. 1. 每个人的工作(有Issue的 ...

  7. Python Fileinput 模块介绍

    作者博文地址:http://www.cnblogs.com/spiritman/ fileinput模块提供处理一个或多个文本文件的功能,可以通过使用for循环来读取一个或多个文本文件的所有行. [默 ...

  8. MySQL 中的数据类型介绍

    1.MySQL 数据类型 MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 2.数值类型(12) 2.1. ...

  9. tcp三次握手 四次挥手 (转)

    转自: http://blog.csdn.net/whuslei/article/details/6667471 建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看 ...

  10. Beautiful Year(拆分四位数)

    Description It seems like the year of 2013 came only yesterday. Do you know a curious fact? The year ...