hiho1123_好配对
题目
给定两个序列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来实现。
实现
- #include<stdio.h>
- #include<string.h>
- #include<iostream>
- #include<string>
- #include<set>
- #include<map>
- #include<vector>
- #include<queue>
- #include<stack>
- #include<unordered_map>
- #include<unordered_set>
- #include<algorithm>
- using namespace std;
- struct Node{
- int val;
- int count;
- int sum;
- int priority;
- Node* childs[2];
- Node(){
- val = count = sum = 0;
- childs[0] = childs[1] = NULL;
- priority = rand();
- }
- void Update(){
- sum = count;
- if (childs[0])
- sum += childs[0]->sum;
- if (childs[1])
- sum += childs[1]->sum;
- }
- };
- struct Treap{
- Node* root;
- Treap(){
- root = NULL;
- }
- void Delete(Node*& node){
- if (!node)
- return;
- if (node->childs[0])
- Delete(node->childs[0]);
- if (node->childs[1])
- Delete(node->childs[1]);
- delete node;
- node = NULL; //注意赋值为NULL,否则在反复使用treap时出错
- }
- void Rotate(Node*& node, bool dir){
- Node* ch = node->childs[dir];
- node->childs[dir] = ch->childs[!dir];
- ch->childs[!dir] = node;
- node->Update(); //注意更新,因为此时修改了树的结构
- node = ch;
- }
- void Insert(Node*& node, int val, int count){
- if (node == NULL){
- node = new Node();
- node->val = val;
- node->sum = node->count = count;
- return;
- }
- if (node->val == val){
- node->count += count;
- node->sum += count;
- return;
- }
- bool ch = node->val < val;
- Insert(node->childs[ch], val, count);
- if (node->childs[ch]->priority > node->priority){
- Rotate(node, ch);
- }
- node->Update(); //更新,此时修改了树的结构
- }
- int Bigger(Node* node, int val){
- if (!node)
- return 0;
- if (node->val == val)
- return (node->childs[1]? node->childs[1]->sum:0);
- else if (node->val < val)
- return Bigger(node->childs[1], val);
- else{
- return (node->childs[1] ? node->childs[1]->sum : 0) + node->count + Bigger(node->childs[0], val);
- }
- }
- };
- int main(){
- int T, n, m, x, y;
- scanf("%d", &T);
- Treap treap;
- while (T--){
- scanf("%d %d", &n, &m);
- treap.Delete(treap.root);
- for (int i = 0; i < n; i++){
- scanf("%d %d", &x, &y);
- treap.Insert(treap.root, x, y);
- }
- long long result = 0;
- for (int i = 0; i < m; i++){
- scanf("%d %d", &x, &y);
- long long int bigger = treap.Bigger(treap.root, x);
- result += y*bigger;
- }
- printf("%lld\n", result);
- }
- return 0;
- }
hiho1123_好配对的更多相关文章
- BZOJ 4205: 卡牌配对
4205: 卡牌配对 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 173 Solved: 76[Submit][Status][Discuss] ...
- SDOI 2016 数字配对
题目大意:给定n个数字以及每个数字的个数和权值,将满足条件的数字配对,使得总代价不小于0,且配对最多 最大费用最大流拆点,对于每个点,连一条由S到该点的边,容量为b,花费为0,再连一条到T的边 对于每 ...
- 【bzoj4514】 Sdoi2016—数字配对
http://www.lydsy.com/JudgeOnline/problem.php?id=4514 (题目链接) 题意 n个数,每个数值为a[i],有b[i]个,权值为c[i].若两个数能配对当 ...
- SPSS数据分析—配对Logistic回归模型
Lofistic回归模型也可以用于配对资料,但是其分析方法和操作方法均与之前介绍的不同,具体表现 在以下几个方面1.每个配对组共有同一个回归参数,也就是说协变量在不同配对组中的作用相同2.常数项随着配 ...
- AC日记——配对碱基链 openjudge 1.7 07
07:配对碱基链 总时间限制: 1000ms 内存限制: 65536kB 描述 脱氧核糖核酸(DNA)由两条互补的碱基链以双螺旋的方式结合而成.而构成DNA的碱基共有4种,分别为腺瞟呤(A).鸟嘌 ...
- 【BZOJ-4514】数字配对 最大费用最大流 + 质因数分解 + 二分图 + 贪心 + 线性筛
4514: [Sdoi2016]数字配对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 726 Solved: 309[Submit][Status ...
- BZOJ4514——[Sdoi2016]数字配对
有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的 ...
- [bzoj4514]数字配对[费用流]
今年SDOI的题,看到他们在做,看到过了一百多个人,然后就被虐惨啦... 果然考试的时候还是打不了高端算法,调了...几天 默默地yy了一个费用流构图: 源连所有点,配对的点连啊,所有点连汇... 后 ...
- bzoj4514: [Sdoi2016]数字配对--费用流
看了一眼题目&数据范围,觉得应该是带下界的费用流 原来想拆点变成二分图,能配对的连边,跑二分图,可行性未知 后来看到另外一种解法.. 符合匹配要求的数要满足:质因子的个数相差为1,且两者可整除 ...
随机推荐
- reactjs入门到实战(三)---- 组件详解
owner >>> 传递 props this >>>是默认指向组件本身 key>>>不能没有,在复用的情况下 组件:例子 <!-- 输入 ...
- ThreadLocal实现线程范围内共享
线程范围内共享,即是对相同一段代码,在不同的模块调用时使用一份数据,而在另外一个线程中又使用另外一份数据. ThreadLocal使用set方法为一个新的线程增加一条记录,key是各自的线程,valu ...
- ios事件传递
http://blog.csdn.net/iefreer/article/details/4754482 本章描述了iPhone操作系统里的事件类型,并解释了如何处理它们.还讨论了怎么在一个应用程序里 ...
- 开源的49款Java 网络爬虫软件
参考地址 搜索引擎 Nutch Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. Nutch的创始人是Doug Cutting, ...
- jQuery Validation remote的缓存请求
不知大家有没有遇到,用jQuery Validation(本文讨论的版本为jQuery Validation Plugin 1.11.1)用remote方式做校验时,如果验证元素的值保持一致,进行多次 ...
- nginx fastcgi 超时问题解决记录
在网站后台导数据时,出现超时的情况.经过网上查找资料和试验 主要在下面几个配置的限制 1.php配置 第一种:set_time_limit(0); 永不过期 第二种: php.ini max_ex ...
- Android 计算器界面
高仿魅族魅蓝NOTE 2风格 <?xml version="1.0" encoding="utf-8"?> <TableLayout xmln ...
- 图片格式转换之ImageMagick
项目中需要实现一些图片文件到TIFF文件的转换,去网上下载了一些第三方软件. 好的软件需要收费,免费的存在各种问题. 自己动手,丰衣足食! 众里寻他千百度,蓦然回首,那人就是ImageMagick. ...
- Spark学习(一)--RDD操作
标签(空格分隔): 学习笔记 Spark编程模型的两种抽象:RDD(Resilient Distributed Dataset)和两种共享变量(支持并行计算的广播变量和累加器). RDD RDD是一种 ...
- PS(photoshop)里A4纸张的像素是多大?
A4纸的尺寸是210mm×297mm, 当你设定的分辨率是72像素/英寸时,A4纸的尺寸的图像的像素是595×842, 当你设定的分辨率是150像素/英寸时,A4纸的尺寸的图像的像素是1240×175 ...