题目

给定两个序列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_好配对的更多相关文章

  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. 用Maonry如何实现UIScrollView

    一,使用UIScrollView 与其他View 布局不同的地方在于, ScrollView的高度/宽度不固定: ScrollView的高度和宽度由其内容决定(即 Scroll View 的 cont ...

  2. SqlSever基础 right函数 从右边开始,截取字符串

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  3. C# this.invoke()作用 多线程操作UI

    Invoke()的作用是:在应用程序的主线程上执行指定的委托.一般应用:在辅助线程中修改UI线程( 主线程 )中对象的属性时,调用this.Invoke(); //测试的窗体 public class ...

  4. 【leetcode❤python】119. Pascal's Triangle II

    #-*- coding: UTF-8 -*-#杨辉三角返回给定行#方法:自上而下考虑问题,从给定的一行计算出下一行,则给定行数之后,计算的最后一行就是求解的最后一行class Solution(obj ...

  5. BZOJ 1061 志愿者招募(最小费用最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061 题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管.布 ...

  6. Cheatsheet: 2014 08.01 ~ 08.31

    Web Slow Server? This is the Flow Chart You're Looking For A Strolll Through Node: Introduction .NET ...

  7. Zookeeper未授权访问

    l 漏洞名称: zookeeper未授权访问 l  漏洞影响版本: zookeeper l  漏洞细节: ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubb ...

  8. postgreSql基础命令及linux下postgreSql命令

    (1)用户实用程序: createdb 创建一个新的PostgreSQL的数据库(和SQL语句:CREATE DATABASE 相同) createuser 创建一个新的PostgreSQL的用户(和 ...

  9. [数据结构与算法]RED-BLACK(红黑)树的实现TreeMap源码阅读

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  10. ServiceStack.OrmLite 学习笔记3 建表

    创建表 前一篇忘记写创建表了,这里补上.(其实前一篇也有那么一点) 建议安装源码里的t4模板看看效果先. public 的属性才有效 在表被创建或者删除的时候执行sql语句 [PostCreateTa ...