主席树套树状数组 动态区间第k小
先打上代码以后更新解释
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define REP(i, s, n) for(int i = s; i <= n; i ++)
#define RAP(i, n, s) for(int i = n; i >= s; i --)
#define LOW for(; x; x -= x & (-x))
using namespace std;
const int maxn = + ;
const int Maxn = ;
const int maxnode = * maxn;
int s[maxnode], ls[maxnode], rs[maxnode], A[maxn], root[maxn], Ln, Rn, L[maxn], R[maxn], c[maxn];
int n, Q, ms = ;
void update(int x, int& y, int L, int R, int pos, int v){
s[y = ++ ms] = s[x] + v;
if(L == R) return ;
int M = L + R >> ;
ls[y] = ls[x]; rs[y] = rs[x];
if(pos <= M) update(ls[x], ls[y], L, M, pos, v);
else update(rs[x], rs[y], M + , R, pos, v);
return ;
}
void update(int x, int v){
for(int i = x; i <= Maxn; i += i & (-i)) update(c[i], c[i], , Maxn, A[x], -); A[x] = v;
for(int i = x; i <= Maxn; i += i & (-i)) update(c[i], c[i], , Maxn, A[x], ); return ;
}
void init(int x, int tp){
if(!tp) { L[++ Ln] = root[x]; LOW if(c[x]) L[++ Ln] = c[x]; }
else { R[++ Rn] = root[x]; LOW if(c[x]) R[++ Rn] = c[x]; }
return ;
}
int query(int ql, int qr, int k){
Ln = Rn = ; init(qr, ); init(ql - , );//0是左
int ll = , rr = Maxn;
while(ll < rr){
int Lsum = , Rsum = , M = ll + rr >> ;
REP(i, , Ln) Lsum += s[ls[L[i]]];
REP(i, , Rn) Rsum += s[ls[R[i]]];
int kth = Rsum - Lsum;
if(kth >= k){//往左找
REP(i, , Ln) L[i] = ls[L[i]];
REP(i, , Rn) R[i] = ls[R[i]];
rr = M;
}
else{//往右找
REP(i, , Ln) L[i] = rs[L[i]];
REP(i, , Rn) R[i] = rs[R[i]];
ll = M + ; k -= kth; //看好了二分! 别忘了还要减 Σ( ° △ °|||)︴
}
}
return ll;
}
inline void read(int &x){
x = ; int sig = ; char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') sig = -; ch = getchar(); }
while(isdigit(ch)) x = * x + ch - '', ch = getchar();
x *= sig; return ;
}
inline void write(int x){
if(x == ) { putchar(''); return ; }
if(x < ) putchar('-'), x = -x;
int len = , buf[];
while(x) buf[len ++] = x % , x /= ;
RAP(i, len - , ) putchar(buf[i] + ''); return ;
}
void init(){
read(n); read(Q);
REP(i, , n) read(A[i]);
REP(i, , n) update(root[i - ], root[i], , Maxn, A[i], );
return ;
}
void work(){
int tp, ql, qr, k, x, v;
while(Q --){
read(tp);
if(tp) read(ql), read(qr), read(k), write(query(ql, qr, k) - ), putchar('\n');// 减一
else read(x), read(v), update(x, v);
}
return ;
}
void print(){ return ;
}
int main(){
init();
work();
print();
return ;
}
逗比版:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define t node[d]
#define cnt countn[d]
#define repnode(d) for(int i=1;i<=countn[d];i++)
using namespace std;
const int maxn=+,maxnode=+,Max=;
int ls[maxnode],rs[maxnode],s[maxnode],root[maxn],A[maxn],c[maxn],n,m,ms=,countn[],node[][maxn],sum[];
void update(int x,int& y,int L,int R,int pos,int d){
s[y=++ms]=s[x]+d;
if(L==R) return;
ls[y]=ls[x];rs[y]=rs[x];
int M=L+R>>;
if(pos<=M) update(ls[x],ls[y],L,M,pos,d);
else update(rs[x],rs[y],M+,R,pos,d);
return;
}
void update(int x,int v){
for(int i=x;i<=Max;i+=i&-i) update(c[i],c[i],,Max,A[x],-);A[x]=v;
for(int i=x;i<=Max;i+=i&-i) update(c[i],c[i],,Max,A[x],);return;
}
void init(int x,int d){
t[++cnt]=root[x];
for(;x;x-=x&-x) if(c[x]) t[++cnt]=c[x];
return;
}
int query(int ql,int qr,int k){
countn[]=countn[]=;
init(qr,);init(ql-,);
int L=,R=Max,d;
while(L<R){
sum[]=sum[]=;
int M=L+R>>;
repnode(d=) sum[d]+=s[ls[t[i]]];
repnode(d=) sum[d]+=s[ls[t[i]]];
int kth=sum[]-sum[];
if(k<=kth){
repnode(d=) t[i]=ls[t[i]];
repnode(d=) t[i]=ls[t[i]];
R=M;
}
else{
repnode(d=) t[i]=rs[t[i]];
repnode(d=) t[i]=rs[t[i]];
L=M+;k-=kth;
}
} return L;
}
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') sig=-;ch=getchar();}
while(isdigit(ch)) x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(int x){
if(x==){putchar('');return;} if(x<) putchar('-'),x=-x;
int len=,buf[]; while(x) buf[len++]=x%,x/=;
for(int i=len-;i>=;i--) putchar(buf[i]+'');return;
}
void init(){
n=read();m=read();
for(int i=;i<=n;i++) A[i]=read();
for(int i=;i<=n;i++) update(root[i-],root[i],,Max,A[i],);
return;
}
void work(){
int tp,i,j,k,x,v;
while(m--){
tp=read();
if(tp){
i=read();j=read();k=read();
write(query(i,j,k)-);putchar('\n');
}
else{
x=read();v=read();
update(x,v);
}
}
return;
}
void print(){
return;
}
int main(){
init();work();print();return ;
}
主席树套树状数组 动态区间第k小的更多相关文章
- 主席树--动态区间第k小
主席树--动态区间第\(k\)小 模板题在这里洛谷2617. 先对几个问题做一个总结: 阅读本文需要有主席树的基础,也就是通过区间kth的模板题. 静态整体kth: sort一下找第k小,时间复杂度\ ...
- 【POJ2104】【整体二分+树状数组】区间第k大
Description You are working for Macrohard company in data structures department. After failing your ...
- G - KiKi's K-Number(树状数组求区间第k大)
For the k-th number, we all should be very familiar with it. Of course,to kiki it is also simple. No ...
- Dynamic Rankings || 动态/静态区间第k小(主席树)
JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...
- 主席树初步学习笔记(可持久化数组?静态区间第k大?)
我接触 OI也快1年了,然而只写了3篇博客...(而且还是从DP跳到了主席树),不知道我这个机房吊车尾什么时候才能摸到大佬们的脚后跟orz... 前言:主席树这个东西,可以说是一种非常畸形的数据结构( ...
- 主席树总结(经典区间第k小问题)(主席树,线段树)
接着上一篇总结--可持久化线段树来整理吧.点击进入 这两种数据结构确实有异曲同工之妙.结构是很相似的,但维护的主要内容并不相同,主席树的离散化.前缀和等思想也要更难理解一些. 闲话 话说刚学习主席树的 ...
- 区间第K小——可持久化线段树模板
概念 可持久化线段树又叫主席树,之所以叫主席树是因为这东西是fotile主席创建出来的. 可持久化数据结构思想,就是保留整个操作的历史,即,对一个线段树进行操作之后,保留访问操作前的线段树的能力. 最 ...
- 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1901 首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊. ...
- ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解
题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...
随机推荐
- 1.1GTK+ 的简单程序HelloWorld
1.1GTK+ 的简单程序HelloWorld 编译执行如图所看到的:
- Android Touch系统简介(二):实例详解onInterceptTouchEvent与onTouchEvent的调用过程
上一篇文章主要讲述了Android的TouchEvent的分发过程,其中有两个重要的函数:onInterceptTouchEvent和onTouchEvent,这两个函数可被重装以完成特定的逻辑.on ...
- 《Android开发艺术探索》读书笔记 (13) 第13章 综合技术、第14章 JNI和NDK编程、第15章 Android性能优化
第13章 综合技术 13.1 使用CrashHandler来获取应用的Crash信息 (1)应用发生Crash在所难免,但是如何采集crash信息以供后续开发处理这类问题呢?利用Thread类的set ...
- tomcat 8.0 安装
tomcat 安装算是非常简单的, 因自己使用ubuntu,所以以下环境均为 ubuntu 操作系统下 tomcat 官方简介 tomcat 各版本下载 这里我使用二进制版本(binary distr ...
- 【转载】ASP.NET线程安全与静态变量的生命周期浅谈
ASP.NET线程安全所涉及的是什么呢?让我们先来看看静态变量的生命周期问题,下面是我理解的静态变量的生命周期: void Application_Start开始 void Application_E ...
- CRT detected that the application wrote to memory after end of heap buffer.
很多人的解释都不一样, 我碰到的问题是,开辟的内存空间小于操作的内存空间.也就是说,我free的内存越界了. 这是我开辟链表结构体内存的代码: PNODE Create() { int len; / ...
- 控制器View的加载过程
1.控制器内部的view是延迟加载 1> 用到时再加载2> 加载完毕后会调用控制器的viewDidLoad方法 2.创建控制器的方式 1> 直接通过代码创建OneViewContro ...
- 关于Core Data的一些整理(二)
关于Core Data的一些整理(二) 创建NSManagedObject的子类时,有一点是在这中间要强调的一点是,要不要勾选 Use scalar properties for primitive ...
- iOS微信支付
SDK接入 服务器签名版本 官方已经是建议使用服务器签名来接入微信支付,实际上从安全上考虑,确实是每个客户端不应该知道RAS密钥,也不需要每个客户端都写一遍签名的算法. 服务端接入流程文档:https ...
- SQL window身份登陆 SQL server不能登陆
用window方式登陆然后,在SQL Server Management Studio 中新建查询,执行下面代码一. ALTER LOGIN sa ENABLE GO ALTER LOGIN sa W ...