Problem

查询区间第k大,但保证区间不互相包含(可以相交)

Solution

只需要对每个区间左端点进行排序,那它们的右端点必定单调递增,不然会出现区间包含的情况。

所以我们暴力对下一个区间加上这个区间没有的点,删去下个区间没有的点。

因为每个点最多被加入,删除1次,所以时间复杂度为O(nlogn)

Notice

当相邻两段区间不相交时,那么我们要先加入点,在删去点。

Code

非旋转Treap

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. #define sqz main
  8. #define ll long long
  9. #define reg register int
  10. #define rep(i, a, b) for (reg i = a; i <= b; i++)
  11. #define per(i, a, b) for (reg i = a; i >= b; i--)
  12. #define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
  13. const int INF = 1e9, N = 100000, M = 50000;
  14. const double eps = 1e-6, phi = acos(-1.0);
  15. ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
  16. ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
  17. if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
  18. void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
  19. int point = 0, T[N + 5], root, ans[M + 5];
  20. struct Node
  21. {
  22. int left, right, ask, id;
  23. }Q[M + 5];
  24. struct node
  25. {
  26. int Size[N + 5], Val[N + 5], Level[N + 5], Son[2][N + 5];
  27. inline void up(int u)
  28. {
  29. Size[u] = Size[Son[0][u]] + Size[Son[1][u]] + 1;
  30. }
  31. int Newnode(int v)
  32. {
  33. int u = ++point;
  34. Val[u] = v, Level[u] = rand();
  35. Size[u] = 1, Son[0][u] = Son[1][u] = 0;
  36. return u;
  37. }
  38. int Merge(int X, int Y)
  39. {
  40. if (X * Y == 0) return X + Y;
  41. if (Level[X] < Level[Y])
  42. {
  43. Son[1][X] = Merge(Son[1][X], Y);
  44. up(X); return X;
  45. }
  46. else
  47. {
  48. Son[0][Y] = Merge(X, Son[0][Y]);
  49. up(Y); return Y;
  50. }
  51. }
  52. void Split(int u, int t, int &x, int &y)
  53. {
  54. if (!u)
  55. {
  56. x = y = 0;
  57. return;
  58. }
  59. if (Val[u] <= t) x = u, Split(Son[1][u], t, Son[1][u], y);
  60. else y = u, Split(Son[0][u], t, x, Son[0][u]);
  61. up(u);
  62. }
  63. void Build(int l, int r)
  64. {
  65. int last, s[N + 5], top = 0;
  66. rep(i, l, r)
  67. {
  68. int u = Newnode(T[i]);
  69. last = 0;
  70. while (top && Level[s[top]] > Level[u])
  71. {
  72. up(s[top]);
  73. last = s[top--];
  74. }
  75. if (top) Son[1][s[top]] = u;
  76. Son[0][u] = last;
  77. s[++top] = u;
  78. }
  79. while (top) up(s[top--]);
  80. root = s[1];
  81. }
  82. int Find_num(int u, int t)
  83. {
  84. if (t <= Size[Son[0][u]]) return Find_num(Son[0][u], t);
  85. else if (t <= Size[Son[0][u]] + 1) return u;
  86. else return Find_num(Son[1][u], t - Size[Son[0][u]] - 1);
  87. }
  88. void Insert(int v)
  89. {
  90. int t = Newnode(v), x, y;
  91. Split(root, v, x, y);
  92. root = Merge(Merge(x, t), y);
  93. }
  94. void Delete(int v)
  95. {
  96. int x, y, z;
  97. Split(root, v, x, z), Split(x, v - 1, x, y);
  98. root = Merge(Merge(x, Merge(Son[0][y], Son[1][y])), z);
  99. }
  100. }Treap;
  101. int cmp(Node X, Node Y)
  102. {
  103. return X.left < Y.left || (X.left == Y.left && X.right < Y.right);
  104. }
  105. int sqz()
  106. {
  107. int n = read(), m = read();
  108. rep(i, 1, n) T[i] = read();
  109. rep(i, 1, m) Q[i].left = read(), Q[i].right = read(), Q[i].ask = read(), Q[i].id = i;
  110. sort(Q + 1, Q + m + 1, cmp);
  111. rep(i, Q[1].left, Q[1].right) Treap.Insert(T[i]);
  112. ans[Q[1].id] = Treap.Val[Treap.Find_num(root, Q[1].ask)];
  113. rep(i, 2, m)
  114. {
  115. rep(j, Q[i - 1].right + 1, Q[i].right) Treap.Insert(T[j]);
  116. rep(j, Q[i - 1].left, Q[i].left - 1) Treap.Delete(T[j]);
  117. ans[Q[i].id] = Treap.Val[Treap.Find_num(root, Q[i].ask)];
  118. }
  119. rep(i, 1, m) printf("%d\n", ans[i]);
  120. return 0;
  121. }

旋转Treap

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. #define sqz main
  8. #define ll long long
  9. #define reg register int
  10. #define rep(i, a, b) for (reg i = a; i <= b; i++)
  11. #define per(i, a, b) for (reg i = a; i >= b; i--)
  12. #define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
  13. const int INF = 1e9, N = 100000, M = 50000;
  14. const double eps = 1e-6, phi = acos(-1.0);
  15. ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
  16. ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
  17. if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
  18. void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
  19. int point = 0, T[N + 5], root, ans[M + 5];
  20. struct node
  21. {
  22. int left, right, ask, id;
  23. }Q[M + 5];
  24. int cmp(node X, node Y)
  25. {
  26. return X.left < Y.left || (X.left == Y.left && X.right < Y.right);
  27. }
  28. struct Node
  29. {
  30. int Val[N + 5], Son[2][N + 5], Level[N + 5], Size[N + 5], Num[N + 5];
  31. inline void up(int u)
  32. {
  33. Size[u] = Size[Son[0][u]] + Size[Son[1][u]] + Num[u];
  34. }
  35. inline void Lturn(int &x)
  36. {
  37. int y = Son[1][x]; Son[1][x] = Son[0][y]; Son[0][y] = x;
  38. up(x), up(y); x = y;
  39. }
  40. inline void Rturn(int &x)
  41. {
  42. int y = Son[0][x]; Son[0][x] = Son[1][y]; Son[1][y] = x;
  43. up(x), up(y); x = y;
  44. }
  45. inline void Newnode(int &u, int v)
  46. {
  47. u = ++point;
  48. Level[u] = rand(), Val[u] = v;
  49. Num[u] = Size[u] = 1, Son[0][u] = Son[1][u] = 0;
  50. }
  51. void Insert(int &u, int t)
  52. {
  53. if (!u)
  54. {
  55. Newnode(u, t);
  56. return;
  57. }
  58. Size[u]++;
  59. if (t == Val[u]) Num[u]++;
  60. else if (t < Val[u])
  61. {
  62. Insert(Son[0][u], t);
  63. if (Level[Son[0][u]] < Level[u]) Rturn(u);
  64. }
  65. else
  66. {
  67. Insert(Son[1][u], t);
  68. if (Level[Son[1][u]] < Level[u]) Lturn(u);
  69. }
  70. }
  71. void Delete(int &u, int t)
  72. {
  73. if (!u) return;
  74. if (Val[u] == t)
  75. {
  76. if (Num[u] > 1)
  77. {
  78. Size[u]--, Num[u]--;
  79. return;
  80. }
  81. if (Son[0][u] * Son[1][u] == 0) u = Son[0][u] + Son[1][u];
  82. else if (Level[Son[0][u]] < Level[Son[1][u]]) Rturn(u), Delete(u, t);
  83. else Lturn(u), Delete(u, t);
  84. }
  85. else if (t < Val[u]) Size[u]--, Delete(Son[0][u], t);
  86. else Size[u]--, Delete(Son[1][u], t);
  87. }
  88. int Find_num(int u, int t)
  89. {
  90. if (!u) return 0;
  91. if (t <= Size[Son[0][u]]) return Find_num(Son[0][u], t);
  92. else if (t <= Size[Son[0][u]] + Num[u]) return u;
  93. else return Find_num(Son[1][u], t - Size[Son[0][u]] - Num[u]);
  94. }
  95. }Treap;
  96. int sqz()
  97. {
  98. int n = read(), m = read();
  99. rep(i, 1, n) T[i] = read();
  100. rep(i, 1, m) Q[i].left = read(), Q[i].right = read(), Q[i].ask = read(), Q[i].id = i;
  101. sort(Q + 1, Q + m + 1, cmp);
  102. rep(i, Q[1].left, Q[1].right) Treap.Insert(root, T[i]);
  103. ans[Q[1].id] = Treap.Val[Treap.Find_num(root, Q[1].ask)];
  104. rep(i, 2, m)
  105. {
  106. if (Q[i].left <= Q[i - 1].right)
  107. {
  108. rep(j, Q[i - 1].left, Q[i].left - 1) Treap.Delete(root, T[j]);
  109. rep(j, Q[i - 1].right + 1, Q[i].right) Treap.Insert(root, T[j]);
  110. }
  111. else
  112. {
  113. rep(j, Q[i - 1].left, Q[i - 1].right) Treap.Delete(root, T[j]);
  114. rep(j, Q[i].left, Q[i].right) Treap.Insert(root, T[j]);
  115. }
  116. ans[Q[i].id] = Treap.Val[Treap.Find_num(root, Q[i].ask)];
  117. }
  118. rep(i, 1, m) printf("%d\n", ans[i]);
  119. return 0;
  120. }

[POJ2761]Feed the dogs的更多相关文章

  1. 【莫队算法】【权值分块】poj2104 K-th Number / poj2761 Feed the dogs

    先用莫队算法保证在询问之间转移的复杂度,每次转移都需要进行O(sqrt(m))次插入和删除,权值分块的插入/删除是O(1)的. 然后询问的时候用权值分块查询区间k小值,每次是O(sqrt(n))的. ...

  2. [POJ2761] Feed the dogs (Treap)

    题目链接:http://poj.org/problem?id=2761 题目大意:给你n个数,m次查询,m次查询分别是a,b,k,查询下表从a到b的第k小元素是哪个.这m个区间不会互相包含. Trea ...

  3. [Poj2761]Feed the dogs(主席树)

    Desciption 题意:求区间第K小(N<=100000) Solution 主席树模板题 Code #include <cstdio> #include <algorit ...

  4. 【POJ2761】【区间第k大】Feed the dogs(吐槽)

    Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs ...

  5. poj 2761 Feed the dogs (treap树)

    /************************************************************* 题目: Feed the dogs(poj 2761) 链接: http: ...

  6. 划分树---Feed the dogs

    POJ  2761 Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to fee ...

  7. poj2761 feed the dog

    题目链接:http://poj.org/problem?id=2761 Description Wind loves pretty dogs very much, and she has n pet ...

  8. POJ 2761 Feed the dogs(平衡树or划分树or主席树)

    Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs ...

  9. POJ 2761 Feed the dogs (主席树)(K-th 值)

                                                                Feed the dogs Time Limit: 6000MS   Memor ...

随机推荐

  1. ArcFace Android 人脸检测与人脸识别集成分享

    目前我们的应用内使用了 ArcFace 的人脸检测功能,其他的我们并不了解,所以这里就和大家分享一下我们的集成过程和一些使用心得集成ArcFace FD 的集成过程非常简单在 ArcFace FD 的 ...

  2. Codeforces 458C - Elections

    458C - Elections 思路: 三分凹形函数极小值域 代码: #include<bits/stdc++.h> using namespace std; #define ll lo ...

  3. redhat 7.0 配置Bond

    把/etc/sysconfig/network-scripts/目录下的ifcfg-bond*文件手动移动到/tmp目录. 重启网络:systemctl restart NetworkManager ...

  4. Birdman Quotes

    Popularity is the slutty little cousin of prestige (威望,声望) . A man becomes a critic when he cannot b ...

  5. xsd与xml和类(class)对象之间的互相转换

    xsd与xml和类(class)对象之间的互相转换 . 第一:通过现有的已经写好的xsd来生成class(.cs)文件. 在您Visual Studio的安装目录下的SDKv2.0Bin中有个应用程序 ...

  6. WCF利用Stream上传大文件

    WCF利用Stream上传大文件 转自别人的文章,学习这个例子,基本上wcf也算入门了,接口用法.系统配置都有了 本文展示了在asp.net中利用wcf的stream方式传输大文件,解决了大文件上传问 ...

  7. IntelliJ IDEA的这些配置,你值得拥有

    一.自动编译开关 二.忽略大小写开关 IDEA默认是匹配大小写,此开关如果未关.你输入字符一定要符合大小写.比如你敲string是不会出现代码提示或智能补充.但是,如果你开了这个开关,你无论输入Str ...

  8. A strange lift HDU - 1548

    There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 ...

  9. BZOJ 1833 数字计数 数位DP

    题目链接 做的第一道数位DP题,听说是最基础的模板题,但还是花了好长时间才写出来..... 想深入了解下数位DP的请点这里 先设dp数组dp[i][j][k]表示数位是i,以j开头的数k出现的次数 有 ...

  10. 6月13 ThinkPHP框架基础

    ThinkPHP 一.php框架基础介绍 真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维 ...