题目链接:【http://acm.split.hdu.edu.cn/showproblem.php?pid=5517】

题意:定义multi_set A<a , d>,B<c , d , e>,C<x , y , z>,给出 A , B ,定义 C = A * B = ={⟨a,c,d⟩∣⟨a,b⟩∈A, ⟨c,d,e⟩∈B and b=e} 。求出C之后,求C中一个元素t[i]<a , b , c>是否存在一个元素tmp<x , y , z>使得 x >= a&&y > =b&&z >= c && t != tmp;如果不存在ans++;输出ans即可。

题解:

  首先,我们要剪枝和去重,加入集合A中存在<1 , 3>,<2, 3>,<3, 3> ,<4, 3>,<4, 3>,那么只需要保留<4,3>就可以了,并且记录一下数量。因为前面的数都可以找到比它大的元素。求出C之后,我们依旧要对C去重。那么这道题就是求C某个元素是否存在大于它的元素了。因为这道题中B set里面c,d,很小在生成的C中y,z也很小,都小于1000,那么我们就可以用二维树状数组做了。首先对C进行从大到小排序,树状数组中只记录y,z的值。我们枚举C中的额每一个元素,先查询(1001 - y ,1001 - z),然后在更新(1001 - y ,1001 -  z),应为是从大到小排序的,所以后面的元素的x值一定小于等于前面的元素的x值,s如果查询不为0,那么一定存在某个元素是大于它的。我们一可以直接套CDQ分治的三维偏序模板,为维护值即可。

树状数组:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int maxn = 1e5 + 15;
  5. int ic, N, M;
  6. struct Point
  7. {
  8. int x, y, z;
  9. LL w;
  10. Point() {}
  11. Point(int x, int y, int z, LL w): x(x), y(y), z(z), w(w) {}
  12. bool operator < (const Point& T) const
  13. {
  14. if(x != T.x) return T.x < x;
  15. if(y != T.y) return T.y < y;
  16. return T.z < z;
  17. }
  18. bool operator == (const Point T) const
  19. {
  20. return (x == T.x && y == T.y && z == T.z);
  21. }
  22. } P[maxn];
  23. int T[maxn], C[maxn];
  24. int Tbit[1050][1050];
  25. int low_bit(int x)
  26. {
  27. return x & -x;
  28. }
  29. void Bit_add(int x, int y, int val)
  30. {
  31. for(int i = x; i <= 1001; i += low_bit(i))
  32. for(int j = y; j <= 1001; j += low_bit(j))
  33. Tbit[i][j] += val;
  34. }
  35. int Bit_sum(int x, int y)
  36. {
  37. int ret = 0;
  38. for(int i = x; i; i -= low_bit(i))
  39. for(int j = y; j; j -= low_bit(j))
  40. ret += Tbit[i][j];
  41. return ret;
  42. }
  43. int main ()
  44. {
  45. scanf("%d", &ic);
  46. for(int cs = 1; cs <= ic; cs++)
  47. {
  48. scanf("%d %d", &N, &M);
  49. memset(T, 0, sizeof(T));
  50. for(int i = 1; i <= N; i++)
  51. {
  52. int a, b;
  53. scanf("%d %d", &a, &b);
  54. if(a > T[b]) T[b] = a, C[b] = 1;
  55. else if(a == T[b]) C[b]++;
  56. }
  57. int tmp = 0;
  58. for(int i = 1; i <= M; i++)
  59. {
  60. int a, b, c;
  61. scanf("%d %d %d", &a, &b, &c);
  62. if(T[c]) P[++tmp] = Point(T[c], a, b, (LL)C[c]);
  63. }
  64. sort(P + 1, P + 1 + tmp);
  65. N = 1;
  66. for(int i = 2; i <= tmp; i++)
  67. {
  68. if(P[i] == P[N]) P[N].w += P[i].w;
  69. else
  70. P[++N] = P[i];
  71. }
  72. LL ans = 0;
  73. memset(Tbit, 0, sizeof(Tbit));
  74. for(int i = 1; i <= N; i++)
  75. {
  76. if(!Bit_sum(1001 - P[i].y, 1001 - P[i].z)) ans += P[i].w;
  77. Bit_add(1001 - P[i].y, 1001 - P[i].z, 1);
  78. }
  79. printf("Case #%d: %lld\n", cs, ans);
  80. }
  81. return 0;
  82. }

三维偏序:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int maxn = 1e5 + 15;
  5. int cs, N, M;
  6. int T[maxn], C[maxn];
  7. LL W[maxn], ans[maxn];
  8. struct Edge
  9. {
  10. int x, y, z, id;
  11. LL w;
  12. Edge() {}
  13. Edge(int x, int y, int z, int id, LL w): x(x), y(y), z(z), id(id), w(w) {}
  14. bool operator < (const Edge & T) const
  15. {
  16. return z < T.z;
  17. }
  18. bool operator == (const Edge & T) const
  19. {
  20. return T.x == x && T.y == y && T.z == z;
  21. }
  22. } B[maxn], p[maxn], t[maxn];
  23. bool cmpx(Edge &a, Edge &b)
  24. {
  25. if(a.x == b.x && a.y == b.y && a.z == b.z)
  26. return a.id < b.id;
  27. else if(a.x == b.x && a.y == b.y)
  28. return a.z < b.z;
  29. else if(a.x == b.x)
  30. return a.y < b.y;
  31. else
  32. return a.x < b.x;
  33. }
  34. bool cmpy(Edge &a, Edge &b)
  35. {
  36. if( a.y == b.y && a.z == b.z)
  37. return a.id < b.id;
  38. else if(a.y == b.y)
  39. return a.z < b.z;
  40. else
  41. return a.y < b.y;
  42. }
  43. //--------------------------------------------------------//树状数组
  44. int c[maxn], maxz = 1001;
  45. inline int lowbit(int x)
  46. {
  47. return x & (-x);
  48. }
  49. void add(int x, int val)
  50. {
  51. while(x <= maxz) c[x] += val, x += lowbit(x);
  52. }
  53. int Get_sum(int x)
  54. {
  55. int ret = 0;
  56. while(x > 0) ret += c[x], x -= lowbit(x);
  57. return ret;
  58. }
  59. //-------------------------------------------------
  60. void cdq(int l, int r)
  61. {
  62. if(l == r) return ;
  63. int mid = (l + r) / 2;
  64. cdq(l, mid), cdq(mid + 1, r);
  65. for(int i = l; i <= r; i++) t[i] = p[i];
  66. sort(t + l, t + mid + 1, cmpy), sort(t + mid + 1, t + r + 1, cmpy);
  67. int a1 = l, a2 = mid + 1;
  68. for(int i = l; i <= r; i++)
  69. {
  70. if(a1 == mid + 1)
  71. ans[t[a2].id] += Get_sum(t[a2].z), a2++;
  72. else if(a2 == r + 1)
  73. add(t[a1].z, 1), a1++;
  74. else if(t[a1].y <= t[a2].y)
  75. add(t[a1].z, 1), a1++;
  76. else
  77. ans[t[a2].id] += Get_sum(t[a2].z), a2++;
  78. }
  79. for(int i = l; i <= mid; i++) add(t[i].z, -1);
  80. }
  81. int main ()
  82. {
  83. scanf("%d", &cs);
  84. for(int ic = 1; ic <= cs; ic++)
  85. {
  86. memset(T, 0, sizeof(T));
  87. memset(ans, 0, sizeof(ans));
  88. scanf("%d %d", &N, &M);
  89. for(int i = 1; i <= N; i++)
  90. {
  91. int a, b;
  92. scanf("%d %d", &a, &b);
  93. if(a > T[b]) T[b] = a, C[b] = 1;
  94. else if(a == T[b]) C[b]++;
  95. }
  96. int tmp = 0;
  97. for(int i = 1; i <= M; i++)
  98. {
  99. int a, b, c;
  100. scanf("%d %d %d", &a, &b, &c);
  101. if(T[c]) ++tmp, p[tmp] = Edge(T[c], a, b, i, (LL)C[c]);
  102. }
  103. sort(p + 1, p + 1 + tmp, cmpx);
  104. N = 1;
  105. for(int i = 2; i <= tmp; i++)
  106. {
  107. if(p[i] == p[N]) p[N].w += p[i].w;
  108. else p[++N] = p[i];
  109. }
  110. if(N <= 1)
  111. {
  112. printf("Case #%d: 0\n", ++ic);
  113. continue;
  114. }
  115. for(int i = 1; i <= N; i++)
  116. {
  117. p[i].x = 100001 - p[i].x;
  118. p[i].y = 1001 - p[i].y;
  119. p[i].z = 1001 - p[i].z;
  120. }
  121. for(int i = 1; i <= N; i++)
  122. {
  123. p[i].id = i;
  124. W[i] = p[i].w;
  125. }
  126. sort(p + 1, p + 1 + N, cmpx);
  127. cdq(1, N);
  128. p[N + 1].x = -1;
  129. for(int i = N; i >= 1; i--)
  130. {
  131. if(p[i].x == p[i + 1].x && p[i].y == p[i + 1].y && p[i].z == p[i + 1].z)
  132. ans[p[i].id] = ans[p[i + 1].id];
  133. }
  134. LL ret = 0;
  135. for(int i = 1; i <= N; i++) if(!ans[i]) ret += W[i];
  136. printf("Case #%d: %lld\n", ic, ret);
  137. }
  138. return 0;
  139. }

  

HDU 5517 【二维树状数组///三维偏序问题】的更多相关文章

  1. hdu 2642 二维树状数组 单点更新区间查询 模板水题

    Stars Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others) Total Subm ...

  2. hdu 2642二维树状数组 单点更新区间查询 模板题

    二维树状数组 单点更新区间查询 模板 从零开始借鉴http://www.2cto.com/kf/201307/227488.html #include<stdio.h> #include& ...

  3. hdu 5517 Triple(二维树状数组)

    Triple Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  4. HDU 5517---Triple(二维树状数组)

    题目链接 Problem Description Given the finite multi-set A of n pairs of integers, an another finite mult ...

  5. 【 HDU - 4456 】Crowd (二维树状数组、cdq分治)

    BUPT2017 wintertraining(15) #5A HDU 4456 题意 给你一个n行n列的格子,一开始每个格子值都是0.有M个操作,p=1为第一种操作,给格子(x,y)增加z.p=2为 ...

  6. HDU 5465 Clarke and puzzle Nim游戏+二维树状数组

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5465 Clarke and puzzle  Accepts: 42  Submissions: 26 ...

  7. HDU1559 最大子矩阵 (二维树状数组)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1559 最大子矩阵 Time Limit: 30000/10000 MS (Java/Others)  ...

  8. hdu6078 Wavel Sequence dp+二维树状数组

    //#pragma comment(linker, "/STACK:102400000,102400000") /** 题目:hdu6078 Wavel Sequence 链接:h ...

  9. BZOJ 3594: [Scoi2014]方伯伯的玉米田 (二维树状数组优化DP)

    分析 首先每次增加的区间一定是[i,n][i,n][i,n]的形式.因为如果选择[i,j](j<n)[i,j](j<n)[i,j](j<n)肯定不如把后面的全部一起加111更优. 那 ...

随机推荐

  1. Oracle分析函数Over()

    一.Over()分析函数 说明:聚合函数(如sum().max()等)可以计算基于组的某种聚合值,但是聚合函数对于某个组只能返回一行记录.若想对于某组返回多行记录,则需要使用分析函数. 1.rank( ...

  2. php 获取唯一字符串与文件扩展名函数

    /** * 生成唯一字符串 * @return string */ function getUniqueStr(){ return md5(uniqid(microtime(true),true)); ...

  3. php中路径斜杠的应用,兼容win与linux

    更多内容推荐微信公众号,欢迎关注: PHP中斜杠的运用 兼容win和linux 使用常量:DIRECTORY_SEPARATOR如:"www".DIRECTORY_SEPARATO ...

  4. 字典树&&01字典树专题&&对字典树的理解

    对于字典树和01字典树的一点理解: 首先,字典树建树的过程就是按照每个数的前缀来的,如果你要存储一个全小写字母字符串,那么这个树每一个节点最多26个节点,这样的话,如果要找特定的单词的话,按照建树的方 ...

  5. mogodb的安装与配置

    下载:https://www.mongodb.com/https://www.mongodb.com/ 安装:一直next,中间选择custom,选择自己的安装路径,最后安装成功. 配置:打开安装好的 ...

  6. Spring4笔记4--基于XML的DI(依赖注入)

    基于XML的DI(依赖注入): Bean 实例在调用无参构造器创建了空值对象后,就要对 Bean 对象的属性进行初始化.初始化是由容器自动完成的,称为注入.根据注入方式的不同,常用的有两类:设值注入. ...

  7. PCI学习之总线原理01

    -----------以下资料由网络资料整理而成-------- PCI即Peripheral Component Interconnect,中文的意思是“外围器件互联”. PCI总线支持32位和64 ...

  8. Python全局变量和局部变量

    全局变量和局部变量 定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域. 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问.调用函数时,所有在函数内声明的变量 ...

  9. python图片处理(三)

    ji那天用到了python图片处理中的二值图像的骨架提取,在matlab中通过输入图像的二值,来处理得到图像的骨架, skelimage = bwmorph(im, 'skel', inf); 在ma ...

  10. mysql慢sql报警系统

    前言:最近有同事反应有的接口响应时间时快时慢,经过排查有的数据层响应时间过长,为了加快定位定位慢sql的准确性,决定简单地搭建一个慢sql报警系统 具体流程如下架构图 第一步:记录日志 每个业务系统都 ...