题目

给定两个序列a和b,每个序列中可能含有重复的数字。 
一个配对(i,j)是一个好配对当从第一个序列中选出一个数ai,再从第二个序列中选出一个数bj且满足ai>bj。 
给出两个序列,问存在多少个好配对。 
题目链接: 好配对

有题目要求,知道题目的数据量比较大:a和b中分别最多有10^5种不同数字,每个数字最多有10^4个。因此,要求算法有O(nlogn)的时间复杂度。 
    一开始使用了两个map,map1为序列a中的数字以及对应的个数构成的数对;map2为对于序列a中的数字x,序列b中小于x的数字的个数。这样在第一次输入序列a,时候创建map1,以及将map2中的value均设置为0;在输入序列b时,若当前读取数值为x,个数为y,从map1的末尾向前查找直到map1中当前的key值小于等于x,在经过的那些(key, value)对中,value均加上y,表示在序列b中小于key值的数字个数增加y个。 
    最后,从头到尾遍历一遍 map1和map2, 求和map1[key]*map2[key]就得到最终结果。 
    结果华丽的超时了: 在对b序列中的每个数字,从末尾到首部遍历map1,构成了O(n^2)的复杂度了。。

超时之后,朝着 O(nlogn)的复杂度方向努力:使用平衡二叉树节点维持数值x,节点中等于x的个数,节点所代表的子树的总数字的个数。在读取序列a的时候,构建这棵平衡二叉树,复杂度为O(nlogn);在读取序列b的时候,对b中的每个数字x,从该平衡二叉树上获得大于x的数字的总个数sum(时间复杂度O(logn),最终结果加上 y*sum. 
总时间复杂度为 O(nlogn) 
    平衡二叉树使用treap来实现。

实现

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<iostream>
  4. #include<string>
  5. #include<set>
  6. #include<map>
  7. #include<vector>
  8. #include<queue>
  9. #include<stack>
  10. #include<unordered_map>
  11. #include<unordered_set>
  12. #include<algorithm>
  13. using namespace std;
  14.  
  15. struct Node{
  16. int val;
  17. int count;
  18. int sum;
  19. int priority;
  20. Node* childs[2];
  21. Node(){
  22. val = count = sum = 0;
  23. childs[0] = childs[1] = NULL;
  24. priority = rand();
  25. }
  26. void Update(){
  27. sum = count;
  28. if (childs[0])
  29. sum += childs[0]->sum;
  30. if (childs[1])
  31. sum += childs[1]->sum;
  32. }
  33. };
  34. struct Treap{
  35. Node* root;
  36. Treap(){
  37. root = NULL;
  38. }
  39. void Delete(Node*& node){
  40. if (!node)
  41. return;
  42. if (node->childs[0])
  43. Delete(node->childs[0]);
  44. if (node->childs[1])
  45. Delete(node->childs[1]);
  46. delete node;
  47. node = NULL; //注意赋值为NULL,否则在反复使用treap时出错
  48. }
  49. void Rotate(Node*& node, bool dir){
  50. Node* ch = node->childs[dir];
  51. node->childs[dir] = ch->childs[!dir];
  52. ch->childs[!dir] = node;
  53. node->Update(); //注意更新,因为此时修改了树的结构
  54. node = ch;
  55. }
  56. void Insert(Node*& node, int val, int count){
  57. if (node == NULL){
  58. node = new Node();
  59. node->val = val;
  60. node->sum = node->count = count;
  61. return;
  62. }
  63. if (node->val == val){
  64. node->count += count;
  65. node->sum += count;
  66. return;
  67. }
  68. bool ch = node->val < val;
  69. Insert(node->childs[ch], val, count);
  70. if (node->childs[ch]->priority > node->priority){
  71. Rotate(node, ch);
  72. }
  73. node->Update(); //更新,此时修改了树的结构
  74. }
  75. int Bigger(Node* node, int val){
  76. if (!node)
  77. return 0;
  78. if (node->val == val)
  79. return (node->childs[1]? node->childs[1]->sum:0);
  80. else if (node->val < val)
  81. return Bigger(node->childs[1], val);
  82. else{
  83. return (node->childs[1] ? node->childs[1]->sum : 0) + node->count + Bigger(node->childs[0], val);
  84. }
  85. }
  86. };
  87.  
  88. int main(){
  89. int T, n, m, x, y;
  90. scanf("%d", &T);
  91. Treap treap;
  92. while (T--){
  93. scanf("%d %d", &n, &m);
  94. treap.Delete(treap.root);
  95. for (int i = 0; i < n; i++){
  96. scanf("%d %d", &x, &y);
  97. treap.Insert(treap.root, x, y);
  98. }
  99. long long result = 0;
  100.  
  101. for (int i = 0; i < m; i++){
  102. scanf("%d %d", &x, &y);
  103. long long int bigger = treap.Bigger(treap.root, x);
  104. result += y*bigger;
  105. }
  106.  
  107. printf("%lld\n", result);
  108. }
  109.  
  110. return 0;
  111. }

hiho1123_好配对的更多相关文章

  1. BZOJ 4205: 卡牌配对

    4205: 卡牌配对 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 173  Solved: 76[Submit][Status][Discuss] ...

  2. SDOI 2016 数字配对

    题目大意:给定n个数字以及每个数字的个数和权值,将满足条件的数字配对,使得总代价不小于0,且配对最多 最大费用最大流拆点,对于每个点,连一条由S到该点的边,容量为b,花费为0,再连一条到T的边 对于每 ...

  3. 【bzoj4514】 Sdoi2016—数字配对

    http://www.lydsy.com/JudgeOnline/problem.php?id=4514 (题目链接) 题意 n个数,每个数值为a[i],有b[i]个,权值为c[i].若两个数能配对当 ...

  4. SPSS数据分析—配对Logistic回归模型

    Lofistic回归模型也可以用于配对资料,但是其分析方法和操作方法均与之前介绍的不同,具体表现 在以下几个方面1.每个配对组共有同一个回归参数,也就是说协变量在不同配对组中的作用相同2.常数项随着配 ...

  5. AC日记——配对碱基链 openjudge 1.7 07

    07:配对碱基链 总时间限制:  1000ms 内存限制:  65536kB 描述 脱氧核糖核酸(DNA)由两条互补的碱基链以双螺旋的方式结合而成.而构成DNA的碱基共有4种,分别为腺瞟呤(A).鸟嘌 ...

  6. 【BZOJ-4514】数字配对 最大费用最大流 + 质因数分解 + 二分图 + 贪心 + 线性筛

    4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 726  Solved: 309[Submit][Status ...

  7. BZOJ4514——[Sdoi2016]数字配对

    有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的 ...

  8. [bzoj4514]数字配对[费用流]

    今年SDOI的题,看到他们在做,看到过了一百多个人,然后就被虐惨啦... 果然考试的时候还是打不了高端算法,调了...几天 默默地yy了一个费用流构图: 源连所有点,配对的点连啊,所有点连汇... 后 ...

  9. bzoj4514: [Sdoi2016]数字配对--费用流

    看了一眼题目&数据范围,觉得应该是带下界的费用流 原来想拆点变成二分图,能配对的连边,跑二分图,可行性未知 后来看到另外一种解法.. 符合匹配要求的数要满足:质因子的个数相差为1,且两者可整除 ...

随机推荐

  1. reactjs入门到实战(三)---- 组件详解

    owner  >>> 传递 props this >>>是默认指向组件本身 key>>>不能没有,在复用的情况下 组件:例子 <!-- 输入 ...

  2. ThreadLocal实现线程范围内共享

    线程范围内共享,即是对相同一段代码,在不同的模块调用时使用一份数据,而在另外一个线程中又使用另外一份数据. ThreadLocal使用set方法为一个新的线程增加一条记录,key是各自的线程,valu ...

  3. ios事件传递

    http://blog.csdn.net/iefreer/article/details/4754482 本章描述了iPhone操作系统里的事件类型,并解释了如何处理它们.还讨论了怎么在一个应用程序里 ...

  4. 开源的49款Java 网络爬虫软件

    参考地址 搜索引擎 Nutch Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. Nutch的创始人是Doug Cutting, ...

  5. jQuery Validation remote的缓存请求

    不知大家有没有遇到,用jQuery Validation(本文讨论的版本为jQuery Validation Plugin 1.11.1)用remote方式做校验时,如果验证元素的值保持一致,进行多次 ...

  6. nginx fastcgi 超时问题解决记录

    在网站后台导数据时,出现超时的情况.经过网上查找资料和试验 主要在下面几个配置的限制 1.php配置 第一种:set_time_limit(0); 永不过期 第二种: php.ini   max_ex ...

  7. Android 计算器界面

    高仿魅族魅蓝NOTE 2风格 <?xml version="1.0" encoding="utf-8"?> <TableLayout xmln ...

  8. 图片格式转换之ImageMagick

    项目中需要实现一些图片文件到TIFF文件的转换,去网上下载了一些第三方软件. 好的软件需要收费,免费的存在各种问题. 自己动手,丰衣足食! 众里寻他千百度,蓦然回首,那人就是ImageMagick. ...

  9. Spark学习(一)--RDD操作

    标签(空格分隔): 学习笔记 Spark编程模型的两种抽象:RDD(Resilient Distributed Dataset)和两种共享变量(支持并行计算的广播变量和累加器). RDD RDD是一种 ...

  10. PS(photoshop)里A4纸张的像素是多大?

    A4纸的尺寸是210mm×297mm, 当你设定的分辨率是72像素/英寸时,A4纸的尺寸的图像的像素是595×842, 当你设定的分辨率是150像素/英寸时,A4纸的尺寸的图像的像素是1240×175 ...