题目传送门

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

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

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

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

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

  1. #include<bits/stdc++.h>
  2. #define clr(a,b) memset(a,b,sizeof(a))
  3. #define fpn() freopen("simple.in","r",stdin)
  4. #define rd read()
  5. using namespace std;
  6. typedef long long ll;
  7. inline int read()
  8. {
  9. int x=,t=;char ch=getchar();
  10. while((ch<''||ch>'')&&ch!='-')ch=getchar();
  11. if(ch=='-')t=-,ch=getchar();
  12. while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
  13. return x*t;
  14. }
  15. const int maxn = ;
  16. int op[maxn],l[maxn],rt[maxn],r[maxn],kk[maxn],a[maxn];
  17. int ls[maxn*],rs[maxn*],sum[maxn*],cnt;
  18. int n,m,s[maxn],tot,tp1[maxn],t1,tp2[maxn],t2;
  19. int lowbit(int x){ return x & -x;};
  20. void Modify(int &now,int l,int r,int p,int w){
  21. if(!now)now=++cnt;
  22. if(l==r){
  23. sum[now]+=w;
  24. return;
  25. }
  26. int mid=(l+r)>>;
  27. if(p<=mid)Modify(ls[now],l,mid,p,w);
  28. else Modify(rs[now],mid+,r,p,w);
  29. sum[now]=sum[ls[now]]+sum[rs[now]];
  30. }
  31. void preModify(int pos,int w){
  32. for(int i=pos;i<=n;i+=lowbit(i)){
  33. Modify(rt[i],,tot,a[pos],w);
  34. }
  35. }
  36. int query(int now,int l,int r,int k){
  37. if(l==r)return sum[now];
  38. int mid=(l+r)>>;
  39. if(k<=mid)return query(ls[now],l,mid,k);
  40. else return sum[ls[now]]+query(rs[now],mid+,r,k);
  41. }
  42. int Rank(int l,int r,int k){
  43. int res=;
  44. l--;
  45. for(int i=r;i>;i-=lowbit(i)){
  46. res+=query(rt[i],,tot,k);
  47. }
  48. for(int i=l;i>;i-=lowbit(i)){
  49. res-=query(rt[i],,tot,k);
  50. }
  51. return res;
  52. }
  53. int kth(int l,int r,int k){
  54. if(l==r)return l;
  55. int su=,mid=(l+r)>>;
  56. for(int i=;i<=t1;i++)su+=sum[ls[tp1[i]]];
  57. for(int i=;i<=t2;i++)su-=sum[ls[tp2[i]]];
  58. if(su>=k){
  59. for(int i=;i<=t1;i++)tp1[i]=ls[tp1[i]];
  60. for(int i=;i<=t2;i++)tp2[i]=ls[tp2[i]];
  61. return kth(l,mid,k);
  62. }else{
  63. for(int i=;i<=t1;i++)tp1[i]=rs[tp1[i]];
  64. for(int i=;i<=t2;i++)tp2[i]=rs[tp2[i]];
  65. return kth(mid+,r,k-su);
  66. }
  67. }
  68. int kthQuery(int l,int r,int k){
  69. l--;
  70. t1=t2=;
  71. for(int i=r;i>;i-=lowbit(i)){
  72. tp1[++t1]=rt[i];
  73. }
  74. for(int i=l;i>;i-=lowbit(i)){
  75. tp2[++t2]=rt[i];
  76. }
  77. return s[kth(,tot,k)];
  78. }
  79. int main(){
  80. //fpn();
  81. n=rd,m=rd;
  82. for(int i=;i<=n;i++){
  83. a[i]=rd;
  84. s[++tot]=a[i];
  85. }
  86. for(int i=;i<=m;i++)
  87. {
  88. op[i]=rd;
  89. if(op[i]!=){
  90. l[i]=rd,r[i]=rd,kk[i]=rd;
  91. if(op[i]!=)s[++tot]=kk[i];
  92. }else{
  93. l[i]=rd,kk[i]=s[++tot]=rd;
  94. }
  95. }
  96. sort(s+,s++tot);
  97. tot=unique(s+,s++tot)-s-;
  98. for(int i=;i<=n;i++)
  99. {
  100. a[i]=lower_bound(s+,s++tot,a[i])-s;
  101. preModify(i,);
  102. }
  103. for(int i=;i<=m;i++)
  104. {
  105. if(op[i]==){
  106. kk[i]=lower_bound(s+,s++tot,kk[i])-s;
  107. printf("%d\n",Rank(l[i],r[i],kk[i]-)+);
  108. }else if(op[i]==){
  109. printf("%d\n",kthQuery(l[i],r[i],kk[i]));
  110. }else if(op[i]==){
  111. preModify(l[i],-);
  112. a[l[i]]=lower_bound(s+,s++tot,kk[i])-s;
  113. preModify(l[i],);
  114. }else if(op[i]==){
  115. kk[i]=lower_bound(s+,s++tot,kk[i])-s;
  116. int gg=Rank(l[i],r[i],kk[i]-);
  117. printf("%d\n",kthQuery(l[i],r[i],gg));
  118. }else{
  119. kk[i]=lower_bound(s+,s++tot,kk[i])-s;
  120. int gg=Rank(l[i],r[i],kk[i]);
  121. printf("%d\n",kthQuery(l[i],r[i],gg+));
  122. }
  123. }
  124. return ;
  125. }

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. 由于挂载的nfs存储目录掉下线,导致创建VM时,无法创建

    具体错误,如下截图 重新挂载存储后,在创建VM,将成功

  2. poj1722 SUBTRACT

    应该是基础的dp练手题 线性dp最主要的就是关于阶段的划分,这个题中我没想到的一点就是开状态的时候使用了前i个数能合成的数来记录 我自己的想法就是类似于区间dp这样的记录方法,这种方法确实开了很多冗余 ...

  3. 使用Sqlserver事务发布实现数据同步(转)

    出处:http://www.cnblogs.com/daizhj/archive/2009/11/18/1605293.html 事务的功能在sqlserver中由来已久,因为最近在做一个数据同步方案 ...

  4. 状态压缩DP----HDU2809

    状态压缩DP的一道较不错的入门题,第二次做这类问题,感觉不是很顺手,故记录下来. 题目的意思就是吕布战群雄,先给你6个数,分别是吕布的攻击值,防御值,生命值,升级后此三值各自的增量,然后是对手的个数n ...

  5. POJ3259 Wormholes(SPFA判断负环)

    Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes ...

  6. 类的 where T : class 泛型类型约束

    where T : struct | T必须是一个结构类型where T : class T必须是一个类(class)类型where T : new() | T必须要有一个无参构造函数where T ...

  7. PostBack

    PostBack 字面意义 Post提交 Back回来. 提交回来. 1. AutoPostBack 服务器控件需要设置 AutoPostBack="true" 后才会提交服务器. ...

  8. c# 简单委托例子

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. python 爬虫proxy,BeautifulSoup+requests+mysql 爬取样例

    实现思路: 由于反扒机制,所以需要做代理切换,去爬取,内容通过BeautifulSoup去解析,最后入mysql库 1.在西刺免费代理网获取代理ip,并自我检测是否可用 2.根据获取的可用代理ip去发 ...

  10. LSI Storcli 工具使用

    查看RAID卡ID 命令功能 查看LSI SAS3108RAID卡的ID. 命令格式 storcli64 show 使用实例 # 查看LSI SAS3108RAID卡的ID. [root@localh ...