洛谷P2617 Dynamic Rankings 主席树 单点修改 区间查询第 K 大
我们将线段树套在树状数组上,查询前预处理出所有要一起移动的节点编号,并在查询过程中一起将这些节点移到左右子树上。
Code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 6000000 + 5;
int A[maxn], arr[maxn];
int n, m, cnt;
struct Queries
{
int c, l, r, k;
Queries(int c = 0, int l = 0, int r = 0, int k = 0):c(c), l(l), r(r), k(k) {}
}asks[maxn];
struct Segment_Tree
{
int lson[maxn * 10], rson[maxn * 10], root[maxn], temp[2][200], count[2], sumv[maxn * 10];
int cnt_Tree;
inline int lowbit(int t)
{
return t & (-t);
}
void insert(int l, int r, int pos, int delta, int &o)
{
if(!o) o = ++cnt_Tree;
sumv[o] += delta;
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid)
insert(l, mid, pos, delta, lson[o]);
else
insert(mid + 1, r, pos, delta, rson[o]);
}
inline void update(int pos, int val, int delta)
{
for(int i = pos;i <= n; i += lowbit(i))
insert(1, n, val, delta, root[i]);
}
int query(int l, int r, int k)
{
if(l == r) return l;
int sum = 0;
for(int i = 1;i <= count[0]; ++i) sum += sumv[lson[temp[0][i]]];
for(int i = 1;i <= count[1]; ++i) sum -= sumv[lson[temp[1][i]]];
int mid = (l + r) >> 1;
if(k <= sum) {
for(int i = 1;i <= count[0]; ++i) temp[0][i] = lson[temp[0][i]];
for(int i = 1;i <= count[1]; ++i) temp[1][i] = lson[temp[1][i]];
return query(l, mid, k);
}
else
{
for(int i = 1;i <= count[0]; ++i) temp[0][i] = rson[temp[0][i]];
for(int i = 1;i <= count[1]; ++i) temp[1][i] = rson[temp[1][i]];
return query(mid + 1, r, k - sum);
}
}
inline int Query(int l, int r, int k)
{
memset(temp, 0, sizeof(temp));
count[0] = count[1] = 0;
for(int i = r;i >= 1;i -= lowbit(i))
temp[0][++count[0]] = root[i];
for(int i = l - 1;i >= 1;i -= lowbit(i))
temp[1][++count[1]] = root[i];
return query(1, n, k);
}
}T;
inline int get(int a)
{
return lower_bound(A + 1, A + 1 + cnt, a) - A;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; ++i)
{
scanf("%d",&arr[i]);
A[i] = arr[i];
}
cnt = n;
for(int i = 1;i <= m; ++i)
{
char opt[3];
scanf("%s",opt);
if(opt[0] == 'Q')
{
int a, b, c;
scanf("%d%d%d",&a,&b,&c);
asks[i] = Queries(0, a, b, c);
}
if(opt[0] == 'C')
{
int a, b;
scanf("%d%d",&a,&b);
asks[i] = Queries(1, a, a, b);
A[++cnt] = b;
}
}
n = cnt;
sort(A + 1, A + 1 + cnt);
for(int i = 1;i <= n; ++i)
{
int cur_num = get(arr[i]);
T.update(i, cur_num, 1);
}
for(int i = 1;i <= m; ++i)
{
if(asks[i].c)
{
int origin_num = get(arr[asks[i].l]);
T.update(asks[i].l, origin_num, -1);
int cur_num = get(asks[i].k);
T.update(asks[i].l, cur_num, 1);
arr[asks[i].l] = asks[i].k;
}
else printf("%d\n", A[T.Query(asks[i].l, asks[i].r, asks[i].k)]);
}
return 0;
}
洛谷P2617 Dynamic Rankings 主席树 单点修改 区间查询第 K 大的更多相关文章
- 洛谷P2617 Dynamic Rankings (主席树)
洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...
- luogu P2617 Dynamic Rankings && bzoj 1901 (带修改区间第k大)
链接:https://www.luogu.org/problemnew/show/P2617 思路: 如果直接在主席树上修改的话,每次修改都会对后面所有的树造成影响,一次修改的复杂度就会变成 : n* ...
- 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 ...
- 洛谷 P2617 Dynamic Rankings || ZOJ - 2112
写的让人看不懂,仅留作笔记 静态主席树,相当于前缀和套(可持久化方法构建的)值域线段树. 建树方法:记录前缀和的各位置的线段树的root.先建一个"第0棵线段树",是完整的(不需要 ...
- 洛谷 P2617 Dynamic Rankings 解题报告
P2617 Dynamic Rankings 题目描述 给定一个含有\(n\)个数的序列\(a[1],a[2],a[3],\dots,a[n]\),程序必须回答这样的询问:对于给定的\(i,j,k\) ...
- 洛谷P2617 Dynamic Rankings
带修主席树模板题 主席树的单点修改就是把前缀和(大概)的形式改成用树状数组维护,每个树状数组的元素都套了一个主席树(相当于每个数组的元素root[i]都是主席树,且这个主席树维护了(i - lowbi ...
- ZOJ -2112 Dynamic Rankings 主席树 待修改的区间第K大
Dynamic Rankings 带修改的区间第K大其实就是先和静态区间第K大的操作一样.先建立一颗主席树, 然后再在树状数组的每一个节点开线段树(其实也是主席树,共用节点), 每次修改的时候都按照树 ...
- 洛谷$P2617\ Dynamic\ Rankings$ 整体二分
正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...
- BZOJ1901 Zju2112 Dynamic Rankings 主席树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1901 题意概括 给你一段序列(n个数),让你支持一些操作(共m次), 有两种操作,一种是询问区间第 ...
随机推荐
- PHP的反射API
PHP5的类和对象并没有告诉我们类内的所有一切,而只是报告了他们的公共成员.要充分了解一个类,需要知道其私有 成员和保护成员,还要知道其方法所期望的参数,对此我们要使用API 1.获得反射API的转储 ...
- ZBrush曲线功能介绍
在ZBrush®中曲线功能是一个非常有用的工具.插入笔刷,曲线笔刷,拓扑和许多地方都会用到它.生成曲线的方式有很多种.可以使用重拓扑引导线,可以使用笔触菜单下曲线功能中的框架网格,可以使用ZBrush ...
- EM_LGH CF965D Single-use Stones 思维_推理
Code: #include<cstdio> #include<algorithm> using namespace std; const int maxn = 1000000 ...
- 路飞学城Python-Day23
1.计算机基础 Python可以实现各种应用软件,类比word.QQ.爱奇艺等,但是应用这些软件需要计算机硬件, 计算机发展的过程就是人类不断的希望机器去取代人力,解放更多的人力,最终极的理想就是完全 ...
- webstorm狂吃内存的解决方法
今天使用webstorm,电脑居然卡死了,我的电脑配置: 运行内存16g,1.5T内存的台式, 后来发现,可以通过设置 内存值大小来解决. 具体办法: 找到WebStorm.exe.vmoptions ...
- codevs 3945 完美拓印 (KMP)
题目大意:给你一个神奇的印章,他左右下三个面都是直的,上面是凸凹不平的面(凸凹都平行于别的面).然后给你一个轮廓线,如果一个面能与轮廓线完全重合,可以把印章的这个沿着轮廓线拓印,求所有的拓印方案. 把 ...
- 基于LXC的虚拟网络自动部署
一.问题: 在搭建以LXC为基础的虚拟网络时,网络参数繁多,配置过程繁琐.面临一个新的网络拓扑结构时,通常要花费大量时间来构建网络.因此,如果能通过配置文件,自动生成相对应的网络拓扑,并生成操作指令. ...
- Python及相应软件安装
Python安装 这是下载地址:Linux下载链接,windows下载链接 1.下载压缩包 wget https://www.python.org/ftp/python/3.7.1/Python-3. ...
- c++里面的单冒号和双冒号
c++ 中的单冒号与双冒号 1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) typedef struct _XXX{ unsigned char a:4; unsigned ...
- Python socket通信之FTP
Python中利用socket进行server端和client端通信是网络编程的基础,是最简单的传输范例. (懂网络的请自动跳过这一部分) 首先,要想通信,必须建立连接,建立连接的过程,需要clien ...