Description

维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作:
1 k,将序列a从小到大排序,输出a_k的值。
2 k,将所有严格大于k的数a_i减去k。

Input

第一行包含两个正整数n,m(1<=n,m<=100000),分别表示序列的长度和操作的个数。
第二行包含n个正整数a_1,a_2,...,a_n(1<=a_i<=10^9),分别表示序列中的每个元素。
接下来m行,每行两个正整数op(1<=op<=2),k,若op=1,则1<=k<=n;若op=2,则1<=k<=10^9;依次描述每个操作。

Output

输出若干行,对于每个询问输出一行一个整数,即第k小的值。
 

感觉怎么做都没什么思路.
学长说正解是分类讨论.
还真是分类讨论...
可以将所有数分为两种:小于等于 $k$ 的,大于 $k$ 的.
前一部分的数值是不变的,大于 $k$ 的数值都要变.
而我们还可以把大于 $k$ 的再分成大于 $2k$ 的和 $k<=a_{i}<=2k.$
而将 $a_{i}\in[k,2k]$ 的数减掉 $k$ 就相当于至少 / 2.
因为没有加法操作,所以每一个数至多会减少 $log(10^9)$ 次.
所以可以每一次用 $splay$ 将 $a_{i}\in[k,2k]$ 之间的数字提取出来,直接暴力减掉 $k$ 并重新插进平衡树.

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn=100003;
  5. namespace IO {
  6. void setIO(string s) {
  7. string in=s+".in";
  8. string out=s+".out";
  9. freopen(in.c_str(),"r",stdin);
  10. freopen(out.c_str(),"w",stdout);
  11. }
  12. char *p1,*p2,buf[100000];
  13. #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
  14. int rd() {
  15. int x=0;
  16. char c=nc();
  17. while(c<48) c=nc();
  18. while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc();
  19. return x;
  20. }
  21. };
  22. int root;
  23. int arr[maxn];
  24. struct Splay {
  25. #define lson ch[x][0]
  26. #define rson ch[x][1]
  27. stack<int>S;
  28. int cnt,tp;
  29. int ch[maxn][2],f[maxn],val[maxn],siz[maxn],tag[maxn],key[maxn];
  30. void init() {
  31. for(int i=1;i<maxn;++i) S.push(i);
  32. }
  33. int newnode() {
  34. int x=S.top();S.pop();
  35. return x;
  36. }
  37. void mark(int x,int d) {
  38. val[x]-=d, tag[x]+=d;
  39. }
  40. int get(int x) {
  41. return ch[f[x]][1]==x;
  42. }
  43. void pushup(int x) {
  44. siz[x]=siz[lson]+siz[rson]+1;
  45. }
  46. void pushdown(int x) {
  47. if(tag[x]) mark(lson,tag[x]),mark(rson,tag[x]),tag[x]=0;
  48. }
  49. void rotate(int x) {
  50. int old=f[x],fold=f[old],which=get(x);
  51. ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
  52. ch[x][which^1]=old,f[old]=x,f[x]=fold;
  53. if(fold) ch[fold][ch[fold][1]==old]=x;
  54. pushup(old),pushup(x);
  55. }
  56. void splay(int x,int &tar) {
  57. int u=f[tar],fa;
  58. for(;(fa=f[x])^u;rotate(x))
  59. if(f[fa]^u)
  60. rotate(get(fa)==get(x)?fa:x);
  61. tar=x;
  62. }
  63. int pre(int v) {
  64. int x=root,re=0;
  65. while(x) {
  66. pushdown(x);
  67. if(val[x]<=v) re=x,x=rson;
  68. else x=lson;
  69. }
  70. return re;
  71. }
  72. int nxt(int v) {
  73. int x=root,re=0;
  74. while(x) {
  75. pushdown(x);
  76. if(val[x]>=v) re=x,x=lson;
  77. else x=rson;
  78. }
  79. return re;
  80. }
  81. void build(int &x,int ff,int l,int r) {
  82. x=newnode();
  83. int mid=(l+r)>>1;
  84. f[x]=ff,val[x]=arr[mid],siz[x]=1;
  85. if(l<mid) build(lson,x,l,mid-1);
  86. if(r>mid) build(rson,x,mid+1,r);
  87. pushup(x);
  88. }
  89. int insert(int &x,int ff,int k) {
  90. if(!x) {
  91. x=newnode();
  92. f[x]=ff,val[x]=k,siz[x]=1;
  93. pushup(x);
  94. return x;
  95. }
  96. pushdown(x);
  97. int a=insert(ch[x][k>val[x]],x,k);
  98. pushup(x);
  99. return a;
  100. }
  101. void dfs(int x) {
  102. if(!x) return;
  103. pushdown(x);
  104. key[++tp]=val[x];
  105. if(lson) dfs(lson);
  106. if(rson) dfs(rson);
  107. S.push(x);
  108. ch[x][0]=ch[x][1]=f[x]=val[x]=siz[x]=tag[x]=0;
  109. }
  110. int kth(int k) {
  111. int x=root;
  112. while(1) {
  113. pushdown(x);
  114. if(k>siz[lson]) {
  115. k-=(siz[lson]+1);
  116. if(k==0) return val[x];
  117. else x=rson;
  118. }
  119. else x=lson;
  120. }
  121. }
  122. void solve(int k) {
  123. int pr=pre(k),nx=nxt(k<<1);
  124. if(!pr) mark(root,k);
  125. else if(!nx) {
  126. splay(pr,root);
  127. int a=ch[root][1];
  128. ch[root][1]=f[ch[root][1]]=0;
  129. pushup(root);
  130. tp=0;
  131. dfs(a);
  132. for(int i=1;i<=tp;++i) {
  133. int cc=insert(root,0,key[i]-k);
  134. if(i%6==0) splay(cc,root);
  135. }
  136. }
  137. else {
  138. splay(pr,root),splay(nx,ch[root][1]);
  139. int a=ch[ch[root][1]][0];
  140. ch[ch[root][1]][0]=0, pushup(ch[root][1]);
  141. tp=0, dfs(a);
  142. mark(ch[root][1], k);
  143. for(int i=1;i<=tp;++i) {
  144. int cc=insert(root,0,key[i]-k);
  145. if(i%6==0) splay(cc,root);
  146. }
  147. }
  148. }
  149. #undef lson
  150. #undef rson
  151. }tr;
  152. int main() {
  153. using namespace IO;
  154. // setIO("input");
  155. tr.init();
  156. int n,m;
  157. n=rd(),m=rd();
  158. for(int i=1;i<=n;++i) arr[i]=rd();
  159. sort(arr+1,arr+1+n);
  160. tr.build(root,0,1,n);
  161. for(int cas=1;cas<=m;++cas) {
  162. int op,k;
  163. op=rd(),k=rd();
  164. if(op==1) printf("%d\n",tr.kth(k));
  165. else tr.solve(k);
  166. }
  167. return 0;
  168. }

  

BZOJ 4923: [Lydsy1706月赛]K小值查询 Splay + 思维的更多相关文章

  1. [BZOJ 4923][Lydsy1706月赛]K小值查询

    传送门 势能分析平衡树,splay或treap都可以 放个指针版的就跑 #include <bits/stdc++.h> using namespace std; #define rep( ...

  2. BZOJ4923:[Lydsy1706月赛]K小值查询(Splay)

    Description 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. In ...

  3. 4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap

    国际惯例的题面:这种维护排序序列,严格大于的进行操作的题都很套路......我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好.显然第一个区间的不会变化,第二个区间的会被平移进第一个区 ...

  4. [BZ4923][Lydsy1706月赛]K小值查询

    K小值查询 题面 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. Input ...

  5. BZOJ4923 [Lydsy1706月赛]K小值查询

    题意 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. \(n \leq 10 ...

  6. [bzoj4923]K小值查询

    来自FallDream的博客,未经允许,请勿转载,谢谢. 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有 ...

  7. BZOJ4923 K小值查询(splay)

    容易想到建一棵平衡树,修改时打上标记即可.但是修改会导致平衡树结构被破坏.注意到实际上只有[k+1,2k)这一部分数在平衡树中的位置会被改变,所以对这一部分暴力修改,因为每次都会使其至少减小一半,复杂 ...

  8. 【BZOJ】3065: 带插入区间K小值

    http://www.lydsy.com/JudgeOnline/problem.php?id=3065 题意:带插入.修改的区间k小值在线查询.(原序列n<=35000, 询问<=175 ...

  9. bzoj 3065: 带插入区间K小值 替罪羊树 && AC300

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1062  Solved: 253[Submit][Status] Des ...

随机推荐

  1. Elasticsearch如何关掉服务

    1.使用head插件找到想关掉的节点进行关停 2.使用命令kill杀掉服务器的ES进程即可1.查找ES进程ps -ef | grep elastic 2.杀掉ES进程kill -9 2382(进程号) ...

  2. mysql安装及相关配置

    安装下载 第一种 安装mysql安装包 //www.jb51.net/softs/451120.html 保存root密码 打开系统偏好设置,start mysql server #配置mysql e ...

  3. LeetCode.876-链表的中间节点(Middle of the Linked List)

    这是悦乐书的第337次更新,第361篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第206题(顺位题号是876).给定具有头节点的非空单链表,返回链表的中间节点.如果有两 ...

  4. lsb-realse

    [root@localhost ~]# lsb_release -a -bash: lsb_release: command not found 解决方法:yum install redhat-lsb ...

  5. kafka学习(四)

    集群成员关系 kafka使用Zookeeper 来维护集群成员的信息.每个broker都有一个唯一标识符,这个标识符可以在配置里指定,也可以自动生成.在broker启动的时候,它通过创建临时节点把自己 ...

  6. 关于cors 跨域的一些问题

    system.webServer节点写配置 <httpProtocol> <customHeaders> <add name="Access-Control-A ...

  7. python+selenium模拟鼠标操作

    from selenium.webdriver.common.action_chains import ActionChains #导入鼠标相关的包 ------------------------- ...

  8. 华南理工大学 “三七互娱杯” G HRY and tree

    https://ac.nowcoder.com/acm/contest/874/G 题目大意:对于一个连通图,现在定义两个点的贡献为连接两点的路径上最大的权值 求任意两个点贡献的和 这个题看懂花了我很 ...

  9. 函数 FUNCTION

    函数 FUNCTION 定义: 带名字的代码块,用于执行具体任务. 注意: 应给函数指定描述性名称,只是用小写字母和下划线. 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 (). 任何 ...

  10. Qfile

    打开方式: void AddStudents::write_to_file(QString src){ QFile file("stu.txt"); if (!file.open( ...