题目传送门

思路:树状数组套线段树模板题。

  什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息,

  其实关键就一句话,把树状数组更新的$sum[x]+=val$改成$Modify(rt[i],1,tot,a[pos],w);$。

  这道题的最大坑点就是分数可能重复,所以对于操作1和操作4要格外的小心,不能直接查,要通过查前面那个位置的数,然后加1得到当前位置(比如1,2,2,3。3的排名是3不是4,而一般的权值线段树,直接查询3可能会出来4)。

  然后就是抄板子抄代码了。

#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
#define fpn() freopen("simple.in","r",stdin)
#define rd read()
using namespace std;
typedef long long ll;
inline int read()
{
int x=,t=;char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-')t=-,ch=getchar();
while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
return x*t;
}
const int maxn = ;
int op[maxn],l[maxn],rt[maxn],r[maxn],kk[maxn],a[maxn];
int ls[maxn*],rs[maxn*],sum[maxn*],cnt;
int n,m,s[maxn],tot,tp1[maxn],t1,tp2[maxn],t2;
int lowbit(int x){ return x & -x;};
void Modify(int &now,int l,int r,int p,int w){
if(!now)now=++cnt;
if(l==r){
sum[now]+=w;
return;
}
int mid=(l+r)>>;
if(p<=mid)Modify(ls[now],l,mid,p,w);
else Modify(rs[now],mid+,r,p,w);
sum[now]=sum[ls[now]]+sum[rs[now]];
}
void preModify(int pos,int w){
for(int i=pos;i<=n;i+=lowbit(i)){
Modify(rt[i],,tot,a[pos],w);
}
}
int query(int now,int l,int r,int k){
if(l==r)return sum[now];
int mid=(l+r)>>;
if(k<=mid)return query(ls[now],l,mid,k);
else return sum[ls[now]]+query(rs[now],mid+,r,k);
}
int Rank(int l,int r,int k){
int res=;
l--;
for(int i=r;i>;i-=lowbit(i)){
res+=query(rt[i],,tot,k);
}
for(int i=l;i>;i-=lowbit(i)){
res-=query(rt[i],,tot,k);
}
return res;
}
int kth(int l,int r,int k){
if(l==r)return l;
int su=,mid=(l+r)>>;
for(int i=;i<=t1;i++)su+=sum[ls[tp1[i]]];
for(int i=;i<=t2;i++)su-=sum[ls[tp2[i]]];
if(su>=k){
for(int i=;i<=t1;i++)tp1[i]=ls[tp1[i]];
for(int i=;i<=t2;i++)tp2[i]=ls[tp2[i]];
return kth(l,mid,k);
}else{
for(int i=;i<=t1;i++)tp1[i]=rs[tp1[i]];
for(int i=;i<=t2;i++)tp2[i]=rs[tp2[i]];
return kth(mid+,r,k-su);
}
}
int kthQuery(int l,int r,int k){
l--;
t1=t2=;
for(int i=r;i>;i-=lowbit(i)){
tp1[++t1]=rt[i];
}
for(int i=l;i>;i-=lowbit(i)){
tp2[++t2]=rt[i];
}
return s[kth(,tot,k)];
}
int main(){
//fpn();
n=rd,m=rd;
for(int i=;i<=n;i++){
a[i]=rd;
s[++tot]=a[i];
}
for(int i=;i<=m;i++)
{
op[i]=rd;
if(op[i]!=){
l[i]=rd,r[i]=rd,kk[i]=rd;
if(op[i]!=)s[++tot]=kk[i];
}else{
l[i]=rd,kk[i]=s[++tot]=rd;
}
}
sort(s+,s++tot);
tot=unique(s+,s++tot)-s-;
for(int i=;i<=n;i++)
{
a[i]=lower_bound(s+,s++tot,a[i])-s;
preModify(i,);
}
for(int i=;i<=m;i++)
{
if(op[i]==){
kk[i]=lower_bound(s+,s++tot,kk[i])-s;
printf("%d\n",Rank(l[i],r[i],kk[i]-)+);
}else if(op[i]==){
printf("%d\n",kthQuery(l[i],r[i],kk[i]));
}else if(op[i]==){
preModify(l[i],-);
a[l[i]]=lower_bound(s+,s++tot,kk[i])-s;
preModify(l[i],);
}else if(op[i]==){
kk[i]=lower_bound(s+,s++tot,kk[i])-s;
int gg=Rank(l[i],r[i],kk[i]-);
printf("%d\n",kthQuery(l[i],r[i],gg));
}else{
kk[i]=lower_bound(s+,s++tot,kk[i])-s;
int gg=Rank(l[i],r[i],kk[i]);
printf("%d\n",kthQuery(l[i],r[i],gg+));
}
}
return ;
}

3196: Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 6185  Solved: 2357
[Submit][Status][Discuss]

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Input

第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

Output

对于操作1,2,4,5各输出一行,表示查询结果

Sample Input

9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5

Sample Output

2
4
3
4
9

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数

bzoj3196 二逼平衡树 树状数组套线段树的更多相关文章

  1. BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...

  2. [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

    题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...

  3. bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Stat ...

  4. [APIO2019] [LOJ 3146] 路灯 (cdq分治或树状数组套线段树)

    [APIO2019] [LOJ 3146] 路灯 (cdq分治或树状数组套线段树) 题面 略 分析 首先把一组询问(x,y)看成二维平面上的一个点,我们想办法用数据结构维护这个二维平面(注意根据题意这 ...

  5. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  6. P3157 [CQOI2011]动态逆序对(树状数组套线段树)

    P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...

  7. BZOJ 1901 Zju2112 Dynamic Rankings 树状数组套线段树

    题意概述:带修改求区间第k大. 分析: 我们知道不带修改的时候直接上主席树就可以了对吧?两个版本号里面的节点一起走在线段树上二分,复杂度是O((N+M)logN). 然而这里可以修改,主席树显然是凉了 ...

  8. 【序列操作IV】树状数组套线段树/树套树

    题目描述 给出序列 a1,a2,…,an(0≤ai≤109),有关序列的两种操作. 1. ai(1≤i≤n)变成 x(0≤x≤109). 2. 求 al,al+1,…,ar(1≤l≤r≤n)第 k(1 ...

  9. 2019南昌网络赛  I. Yukino With Subinterval 树状数组套线段树

    I. Yukino With Subinterval 题目链接: Problem Descripe Yukino has an array \(a_1, a_2 \cdots a_n\). As a ...

随机推荐

  1. linux下配置eclipse环境

    注明:本文为博主原创文章,转载请注明出处 前期准备 (此文使用的是非安装版jdk1.8,你也可以下载版本更低的,而且建议使用1.6版本,66大顺嘛,嘻嘻) 1.点击下载jdk 2.点击下载eclips ...

  2. 网页中的foot底部定位问题

    有时候,我们会碰到这样一个问题. 网页底部一般有个foot对吧,放置一些友情链接版权声明什么的,这个模块是如何定位的? 要是直接放内容区域的下面的话,假如是内容区域的高度不够的话,那么foot下面是会 ...

  3. Charles安装证书ssl proxying

    1.找到工具栏上方的 help 按钮 2.help下面有一个 ssl proxying的选项,点击ssl proxying 选择里面的第三个:install charles root certific ...

  4. Capturing ASP.NET Application Startup Exceptions

    It has become common practice to perform tasks during an ASP.NET applications start up process. Thes ...

  5. Network in Network(NiN)

    - Mlpconv layer with "micronetwork" with each conv layer to compute more abstract features ...

  6. JAVA的IO处理【转】

    I/O简介 IO是输入和输出的简称,在实际的使用时,输入和输出是有方向的.就像现实中两个人之间借钱一样,例如A借钱给B,相对于A来说是借出,而相对于B来说则是借入.所以在程序中提到输入和输出时,也需要 ...

  7. delphi将图片转换成Base64编码函数

    {************************************************************************** 名称: BaseImage 参数: fn: TF ...

  8. 使用JS完成首页定时弹出广告图片

    一.需求分析 在首页中的顶部做一个定时弹出广告图片. 二.技术分析 隐藏图片: display: none        定时操作: setInterval(“显示图片的函数”, 3000); 三.代 ...

  9. winform treeview绑定数据 DOM操作

    form1 public void treeView() { // datatable 定义变量接收 传归来的值 DataTable Father = new BuMenDA().ConSql(); ...

  10. [转]Marshaling a SAFEARRAY of Managed Structures by P/Invoke Part 5.

    1. Introduction. 1.1 In part 4, I have started to discuss how to interop marshal a managed array tha ...