3110 [Zjoi2013]K大数查询

有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

Input

第一行N,M
接下来M行,每行形如1 a b c或2 a b c

Output

输出每个询问的结果

Sample Input

2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3

Sample Output

1
2
1

HINT

【样例说明】

第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1

的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是

1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3

大的数是 1 。‍

N,M<=50000,N,M<=50000

a<=b<=N

1操作中abs(c)<=N

2操作中c<=Maxlongint

题解:


题意概括

  有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c。如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中c<=Maxlongint


题解

  让我们来考虑神奇的分治算法。

  整体二分!!(当你会了)

  首先当你已经掌握了树状数组的区间加和区间询问(如果不会->点这里

  我们考虑二分答案。

  注意进行以下操作要严格按照输入时间先后顺序来。

  首先对于加进去的数字c,我们把他变成n-c+1,这样就把询问前k大变成了前k小。

  如果是修改操作,如果修改的值比当前的mid值小,就修改,并扔到左区间里面。否则扔到右边。

  如果是询问操作,如果在当前的状态下,该询问的区间内查询到的数的个数res比当前询问的c要大(或者相等),那么显然答案在左区间,把他扔到左边,否则把他的c减掉res再扔到右边去。

  然后递归分治两个区间就可以了。

  (本质是个二分答案的升级版)

  

参考代码:

  1. /**************************************************************
  2. Problem: 3110
  3. User: SongHL
  4. Language: C++
  5. Result: Accepted
  6. Time:1880 ms
  7. Memory:3640 kb
  8. ****************************************************************/
  9.  
  10. #include<bits/stdc++.h>
  11. using namespace std;
  12. #define lowbit(x) x&-x
  13. #define clr(a,b) memset(a,b,sizeof a)
  14. typedef long long ll;
  15. const int maxn=;
  16. int n,m,id[maxn],templ[maxn],tempr[maxn];
  17. ll tree[][maxn];
  18. inline int read()
  19. {
  20. int x=,f=;char ch=getchar();
  21. while(ch<''||ch>'') {if(ch=='-') f=-;ch=getchar();}
  22. while(ch>=''&&ch<='') {x=x*+ch-''; ch=getchar();}
  23. return x*f;
  24. }
  25. inline void add(int t,int x,int y)//单点加
  26. {
  27. while(x<=n+)
  28. {
  29. tree[t][x]+=y;
  30. x+=lowbit(x);
  31. }
  32. }
  33. inline void update(int l,int r,int val)//区间加
  34. {
  35. add(,l,val);add(,l,l*val);
  36. add(,r+,-val);add(,r+,-val*(r+));
  37. }
  38. inline ll Sum(int t,int x)//前缀和
  39. {
  40. ll ans=;
  41. while(x>)
  42. {
  43. ans+=tree[t][x];
  44. x-=lowbit(x);
  45. }
  46. return ans;
  47. }
  48. inline ll query(int l,int r)//区间求和
  49. {
  50. return Sum(,r)*(r+)-Sum(,l)*l-Sum(,r)+Sum(,l);
  51. }
  52. struct Node{
  53. int type,l,r,x,ans;
  54. void Get()
  55. {
  56. type=read();l=read();r=read();x=read();
  57. if(type==) x=n-x+;
  58. }
  59. } a[maxn];
  60.  
  61. inline void Solve(int lx,int rx,int l,int r)
  62. {
  63. if(l>r) return ;
  64. if(lx==rx)
  65. {
  66. for(int i=l;i<=r;++i) a[id[i]].ans=lx;
  67. return ;
  68. }
  69. int midx=lx+rx>>;
  70. int L=,R=;
  71. for(int i=l;i<=r;++i)
  72. {
  73. if(a[id[i]].type==)
  74. {
  75. if(a[id[i]].x<=midx) templ[++L]=id[i],update(a[id[i]].l,a[id[i]].r,);
  76. else tempr[++R]=id[i];
  77. }
  78. else
  79. {
  80. ll res=query(a[id[i]].l,a[id[i]].r);
  81. if(res>=a[id[i]].x) templ[++L]=id[i];
  82. else tempr[++R]=id[i],a[id[i]].x-=res;
  83. }
  84. }
  85. for(int i=;i<=L;++i)
  86. {
  87. if(a[templ[i]].type==)
  88. update(a[templ[i]].l,a[templ[i]].r,-);
  89. }
  90.  
  91. for(int i=l;i<=l+L-;++i) id[i]=templ[i-(l-)];
  92. for(int i=r-R+;i<=r;++i) id[i]=tempr[i-(r-R)];
  93.  
  94. Solve(lx,midx,l,l+L-);
  95. Solve(midx+,rx,r-R+,r);
  96. }
  97.  
  98. int main()
  99. {
  100. n=read();m=read();
  101. for(int i=;i<=m;++i) a[i].Get(),id[i]=i;
  102. clr(tree,);
  103. Solve(,*n+,,m);
  104. for(int i=;i<=m;++i)
  105. if(a[i].type==) printf("%d\n",n-a[i].ans+);
  106. return ;
  107. }

  

BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)的更多相关文章

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

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

  2. BZOJ 3110: [Zjoi2013]K大数查询( 树状数组套主席树 )

    BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N)) ---------------------------------------------------- ...

  3. BZOJ3110 [Zjoi2013]K大数查询 树套树 线段树 整体二分 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3110 题意概括 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位 ...

  4. [BZOJ3110] [Zjoi2013] K大数查询 (树套树)

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置 ...

  5. Cogs 1345. [ZJOI2013] K大数查询(树套树)

    [ZJOI2013] K大数查询 /* 树套树写法. bzoj过不了. 可能有负数要离散吧. 线段树套线段树. 外层权值线段树,内层区间线段树维护标记. 对权值建一棵权值线段树. 某个点表示权值在某个 ...

  6. 【BZOJ3110】[Zjoi2013]K大数查询 树套树

    [BZOJ3110][Zjoi2013]K大数查询 Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c,如果 ...

  7. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

  8. BZOJ3110: [Zjoi2013]K大数查询

    喜闻乐见的简单树套树= =第一维按权值建树状数组,第二维按下标建动态开点线段树,修改相当于第二维区间加,查询在树状数组上二分,比一般的线段树还短= =可惜并不能跑过整体二分= =另外bzoj上的数据有 ...

  9. [BZOJ3110][ZJOI2013]K大数查询(整体二分)

    BZOJ Luogu sol 整体二分,其实很简单的啦. 对所有询问二分一个答案mid,把所有修改操作中数字大于mid的做一个区间覆盖(区间加1) 查询就是区间查询 然后左右分一分即可 注意是第k大 ...

随机推荐

  1. 什么是ping通

    ping这个命令是用来检测你的电脑和你所输入的IP地址127.0.01是否有数据通讯,以判断网络通不通的问题,执行这个命令也很简单,在开始——运行,输入ping 127.0.01,上面会出现一些数据, ...

  2. Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 - 推酷 - 360安全浏览器 7.1

    Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 时间 2014-02-11 21:08:00  博客园-所有随笔区 ...

  3. T-SQL Part X: UNION, EXCEPT and INTERSECT

    MSDN上关于EXCEPT和INTERSECT的文档.MSDN上关于UNION的文档. 值得注意的是,UNION其实有两种,一种是普通的UNION,另外一种是UNION ALL.加上EXCEPT和IN ...

  4. python3 控制安卓手机的飞行模式遇到的问题汇总

    一.首先调通电脑对手机能落实 adb shell命令 验证通过标准:控制wifi开关的命令,能让wifi功能开启和关闭 (adb shell svc wifi enable   和   adb she ...

  5. [LC]206题 Reverse Linked List (反转链表)(链表)

    ①英文题目 Reverse a singly linked list. Example: Input: 1->2->3->4->5->NULL Output: 5-> ...

  6. requests模块发送带headers的Get请求和带参数的请求

    1.在PyCharm开发工具中新建try_params.py文件: 2.try_params.py文件中编写代码: import requests#设置请求Headers头部header = {&qu ...

  7. 决策树(中)-集成学习、RF、AdaBoost、Boost Tree、GBDT

    参考资料(要是对于本文的理解不够透彻,必须将以下博客认知阅读): 1. https://zhuanlan.zhihu.com/p/86263786 2.https://blog.csdn.net/li ...

  8. 力扣(LeetCode)两数相加 个人题解

    给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和 ...

  9. wait()、notify、notifyAll()的使用

    wait().notify.notifyAll()的使用 参考:https://www.jianshu.com/p/25e243850bd2?appinstall=0 一).java 中对象锁的模型 ...

  10. day 17 re模块 正则表达式

    import re    引用re模块 查找 finall:匹配所有,每一项都是列表中的一个元素 search:只匹配从左到右的第一个,得到的不是直接的结果而是一个变量,通过group方法获取结果,没 ...