1、Dynamic Rankings

区间带修改的第 \(k\) 大需要用带修改主席树。

如果用平常的主席树的效率是多少呢?

查询 \(O(logn)\),暴力修改 \(O(nlogn)\),时间不支持

那么就需要平衡一下两者的时间复杂度

我们用树状数组套主席树,每次查询把 \(logn\) 个 \(rt\) 取出来,\(l-1\) 和 \(r\) 的 \(sum\) 相减一下,在值域进行 \(logn\) 的遍历,时间复杂度 \(O(nlog^2n)\)

int query(int l,int r,int k){if(l == r) return l;int x=0,mid=(l+r)>>1;for(int i=1;i<=cnt1;i++) x-=sum[L[lT[i]]];for(int i=1;i<=cnt2;i++) x+=sum[L[rT[i]]];if(x >= k){for(int i=1;i<=cnt1;i++) lT[i]=L[lT[i]];for(int i=1;i<=cnt2;i++) rT[i]=L[rT[i]];return query(l,mid,k);}else {for(int i=1;i<=cnt1;i++) lT[i]=R[lT[i]];for(int i=1;i<=cnt2;i++) rT[i]=R[rT[i]];return query(mid+1,r,k-x);}
}

每次修改在树状数组上,遍历到一个点就 \(update\),动态开点

void update(int &now,int l,int r,int x,int v){if(!now) now=++tot;sum[now]+=v;if(l == r) return ;int mid=(l+r)>>1;if(x <= mid) update(L[now],l,mid,x,v);else update(R[now],mid+1,r,x,v);
}void add(int x,int v){for(int i=x;i<=n;i+=lowbit(i))update(T[i],1,n,a[x],v);
}

每次修改要新开一条链上 \(logn\) 个结点,一共执行 \(logn\) 次,空间复杂度 \(O(nlog^2n)\)

不难证明时间复杂度 \(O(nlog^2n)\)

\(Code\ Below:\)

#include <bits/stdc++.h>
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],mp[maxn<<1],cnt;
int T[maxn],lT[maxn],rT[maxn],L[maxn*400],R[maxn*400],sum[maxn*400],tot,cnt1,cnt2;struct Query{int opt,l,r,k;
}q[maxn];inline int read(){register int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return (f==1)?x:-x;
}void update(int &now,int l,int r,int x,int v){if(!now) now=++tot;sum[now]+=v;if(l == r) return ;int mid=(l+r)>>1;if(x <= mid) update(L[now],l,mid,x,v);else update(R[now],mid+1,r,x,v);
}void add(int x,int v){for(int i=x;i<=n;i+=lowbit(i)) update(T[i],1,cnt,a[x],v);
}int query(int l,int r,int k){if(l == r) return l;int x=0,mid=(l+r)>>1;for(int i=1;i<=cnt1;i++) x-=sum[L[lT[i]]];for(int i=1;i<=cnt2;i++) x+=sum[L[rT[i]]];if(x >= k){for(int i=1;i<=cnt1;i++) lT[i]=L[lT[i]];for(int i=1;i<=cnt2;i++) rT[i]=L[rT[i]];return query(l,mid,k);}else {for(int i=1;i<=cnt1;i++) lT[i]=R[lT[i]];for(int i=1;i<=cnt2;i++) rT[i]=R[rT[i]];return query(mid+1,r,k-x);}
}int main()
{n=read(),m=read();for(int i=1;i<=n;i++) mp[++cnt]=a[i]=read();char ch;for(int i=1;i<=m;i++){ch=getchar();while(!isalpha(ch)) ch=getchar();q[i].opt=(ch=='Q')?1:2;if(q[i].opt==1) q[i].l=read(),q[i].r=read(),q[i].k=read();else q[i].l=read(),mp[++cnt]=q[i].k=read();}sort(mp+1,mp+cnt+1);cnt=unique(mp+1,mp+cnt+1)-mp-1;for(int i=1;i<=n;i++) a[i]=lower_bound(mp+1,mp+cnt+1,a[i])-mp,add(i,1);for(int i=1;i<=m;i++){if(q[i].opt==1){cnt1=cnt2=0;for(int j=q[i].l-1;j>0;j-=lowbit(j)) lT[++cnt1]=T[j];for(int j=q[i].r;j>0;j-=lowbit(j)) rT[++cnt2]=T[j];printf("%d\n",mp[query(1,cnt,q[i].k)]);}else {q[i].k=lower_bound(mp+1,mp+cnt+1,q[i].k)-mp;add(q[i].l,-1);a[q[i].l]=q[i].k;add(q[i].l,1);}}return 0;
}

2、 [CQOI2011]动态逆序对

先用树状数组求一下总的逆序对

然后每次就减去当前在 \([1,pos[x]-1]\) 中大于 \(x\) 的数的个数和当前在 \([pos[x]+1,n]\) 中小于 \(x\) 的数

带修改主席树即可,时间复杂度 \(O(nlog^2n)\),空间复杂度 \(O(nlog^2n)\)

\(Code\ Below:\)

#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],pos[maxn];ll ans;
int T[maxn],lT[maxn],rT[maxn],L[maxn*400],R[maxn*400],sum[maxn*400],tot,cnt1,cnt2;inline int read(){register int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return (f==1)?x:-x;
}namespace unorder_pair{struct Binary_Index_Tree{int c[maxn];void update(int x,int y){for(;x<=n;x+=lowbit(x)) c[x]+=y;}int sum(int x){int ans=0;for(;x;x-=lowbit(x)) ans+=c[x];return ans;}}T;ll solve(){ll ans=0;for(int i=n;i>=1;i--){ans+=T.sum(a[i]);T.update(a[i],1);}return ans;}
}void update(int &now,int l,int r,int x,int v){if(!now) now=++tot;sum[now]+=v;if(l == r) return ;int mid=(l+r)>>1;if(x <= mid) update(L[now],l,mid,x,v);else update(R[now],mid+1,r,x,v);
}void add(int x,int v){for(int i=x;i<=n;i+=lowbit(i))update(T[i],1,n,a[x],v);
}int query(int l,int r,int v,int sta){if(l>r) return 0;cnt1=cnt2=0;for(int i=l-1;i>0;i-=lowbit(i)) lT[++cnt1]=T[i];for(int i=r;i>0;i-=lowbit(i)) rT[++cnt2]=T[i];l=1,r=n;int mid,ans=0;while(l!=r){mid=(l+r)>>1;if(mid < v){if(!sta){for(int i=1;i<=cnt1;i++) ans-=sum[L[lT[i]]];for(int i=1;i<=cnt2;i++) ans+=sum[L[rT[i]]];}for(int i=1;i<=cnt1;i++) lT[i]=R[lT[i]];for(int i=1;i<=cnt2;i++) rT[i]=R[rT[i]];l=mid+1;}else {if(sta){for(int i=1;i<=cnt1;i++) ans-=sum[R[lT[i]]];for(int i=1;i<=cnt2;i++) ans+=sum[R[rT[i]]];}for(int i=1;i<=cnt1;i++) lT[i]=L[lT[i]];for(int i=1;i<=cnt2;i++) rT[i]=L[rT[i]];r=mid;}}return ans;
}int main()
{n=read(),m=read();for(int i=1;i<=n;i++) a[i]=read(),pos[a[i]]=i;ans=unorder_pair::solve();for(int i=1;i<=n;i++) add(i,1);int x;for(int i=1;i<=m;i++){x=read();printf("%lld\n",ans);ans-=(ll)query(1,pos[x]-1,x,1);ans-=(ll)query(pos[x]+1,n,x,0);add(pos[x],-1);}return 0;
}

转载于:https://www.cnblogs.com/owencodeisking/p/9978768.html

[学习笔记]带修改主席树相关推荐

  1. P2617 Dynamic Rankings(带修改主席树)

    P2617 Dynamic Rankings 带修改主席树 能进行对序列中数进行修改 #include<iostream> #include<string.h> #includ ...

  2. zoj - 2112 带修改主席树 + 空间优化

    ZOJ - 2112 题意:求区间第k小 思路:带修改区间第k小裸题,无修改的主席树是维护一个前缀线段树,每次更新log个节点,用root 和 ls rs作为每颗前缀线段树的根节点和左右子树的索引(相 ...

  3. 区块链学习笔记15——ETH状态树

    区块链学习笔记15--ETH状态树 学习视频:北京大学肖臻老师<区块链技术与应用> 笔记参考:北京大学肖臻老师<区块链技术与应用>公开课系列笔记--目录导航页 引入 要实现的功 ...

  4. 2019年ACM-ICPC - 南昌网络赛I:Yukino With Subinterval【带修主席树】

    题目: 2019ICPC南昌网络赛I:Yukino With Subinterval 题意: 给定长度为 N 的数组,有两种操作:(1)单点修改,(2)查询区间[qL,qR]内有多少个不同的段(连续相 ...

  5. 数据结构专题-学习笔记:李超线段树

    数据结构专题 - 学习笔记:李超线段树 1. 前言 2. 详解 3. 应用 4. 总结 5. 参考资料 1. 前言 本篇博文是博主学习李超线段树的学习笔记. 2020/12/21 的时候我在 线段树算 ...

  6. P2617 Dynamic Rankings(带修主席树)

    所谓带修主席树,就是用树状数组的方法维护主席树的前缀和 思路 带修主席树的板子 注意数据范围显然要离散化即可 代码 #include <cstdio> #include <cstri ...

  7. 区块链学习笔记16——ETH交易树和收据树

    区块链学习笔记16--ETH交易树和收据树 学习视频:北京大学肖臻老师<区块链技术与应用> 笔记参考:北京大学肖臻老师<区块链技术与应用>公开课系列笔记--目录导航页 交易树和 ...

  8. Git学习笔记:修改

    前言 在补习python的时候主要参考的是廖雪峰的教程Python教程,在学习完后准备完成期末作业时,遇到了一个技术难题,需要初步掌握git,因此开始了git的学习. 本教程参考廖雪峰的Git教程 G ...

  9. 【学习笔记+习题集】(树状数组)(9473字)

    目录 板块一:树状数组 引子:lowbit 1.存入数据(单点修改) 2.区间查询 练习1:hdoj1541 3.区间修改和单点查询(差分数组) 练习1:hdoj 1556 练习2:洛谷P3368 4 ...

最新文章

  1. 写论文查论文查参考文献
  2. CSS reset 标签初始化设置
  3. SGU 248. Integer Linear Programming( 背包dp )
  4. 每日英语:Why Sit Up Straight?
  5. else 策略模式去掉if_业务复杂=if else?刚来的大神竟然用策略+工厂彻底干掉了他们!...
  6. 使用ffmpeg捕获USB外部摄像头视频流
  7. JAVA笔记:double四舍五入并保留两位小数的方法
  8. 第6章 见缝插圆(《C和C++游戏趣味编程》配套教学视频)
  9. 难怪各家抢滩物联网!真实原因竟是……
  10. 渐进式Web应用程序居然是Web开发的未来
  11. 让在vc6创建的程序中,控件可以随xp风格的改变而变化,不用再程序中添加代码来自己实现~...
  12. java linux ifstat,ifstat命令
  13. 开始做我的robot博客
  14. OFFICE技术讲座:双层字体引擎的提出
  15. 七月算法机器学习 8 信息论、最大熵模型与EM算法
  16. java 手机号码归属地_Java获取手机号码归属地
  17. matlab车牌倾斜校正,求做车牌倾斜校正程序。
  18. SpringBoot(30) 整合PageOffice实现在线编辑Word和Excel
  19. 计算机什么快捷键是睡眠,电脑睡眠快捷键(ctrl加哪个键是睡眠)
  20. access to同义替换_access to 用法

热门文章

  1. 第十三节、SURF特征提取算法
  2. 201671010135 2016--2017java程序设计对java的初步认识和对第一,二章的总结(0)
  3. 对现代软件工程开发看法
  4. 父框架与子框架的互操作
  5. 2014多校第一场A题 || HDU 4861 Couple doubi
  6. Memory Ordering
  7. python连数据库课程设计_python 连接操作 各类数据库
  8. python partition函数_在Python中相当于R的createDataPartition
  9. Dizzy Cows(拓扑)
  10. 又见斐波那契数列(矩阵构造+矩阵快速幂)