题目链接:眼红的同学

题干信息很简单,看到数据量之后就不简单了。在数据量小的时候可以使用双层循环暴力的方法来求答案。显然对于这道题而言O(n^2)是完全过不去的。

前置知识:

  1. 使用树状数组求逆序对
  2. 会归并排序等分治算法。

如果想要了解跟多信息,可以自行在搜索引擎搜索有关CDQ分治的练习题。

考虑使用分治算法来解决,这是一道经典的三维偏序问题。对于这种坐标相关题目,一个很常见的方法是先对其中一个纬度进行排序。这样子控制一个纬度之后再去查找速度就会快很多。

例如如果控制语文成绩这个维度,按照从大到小的顺序排序后可以得出以下结论:

第i位同学的嫉妒值一定只会被前i-1位同学所影响,排在i后面的所有学生都不会贡献为第i为同学贡献嫉妒值。

接下来的做法跟分治逆序对很像,每次将所有的数字分成两半,以任意一个k为分界线,保证第k个学生的语文成绩低于第k+1个学生的成绩即可。直至区间的长度为1。

由于前半部分的x肯定比后半部分的x要大,可以按照数学成绩再分别被前半部分和后半部分的学生进行排序。这样子依然也不会损失单调性,只要保证前半部分x都比后半部分x大即可。接下来我们就可以遍历 后半部分,在遍历的时候计算单个点所获得的贡献(这些贡献来自于前半部分)。

截至目前已经对两个纬度进行排序了,最后一个纬度可以使用树状数组进行维护。这部分可以借用树状数组求逆序对的思想(请自行查阅)。

时间复杂度也比较好计算,分治的时间复杂度为\(O(log(n) \times n)\)。但是树状数组的单点修改和区间查询也分别是\(O(\log(n))\)级别的。综合下来时间复杂度在\(O(n \times \log(n)^2)\)附近。因为题输入数据比较大,注意常数优化。

参考代码如下:

#include <iostream>
#include <algorithm>
#define int long long
using namespace std; const int MAXN = 3e5 + 5;
int maximum;
int n, ans[MAXN];
int L[MAXN], R[MAXN];
int bit[MAXN << 1];
struct student{
int x, y, z;
int id, ans, val;
} arr[MAXN]; bool cmp1(student a, student b){
if (a.x != b.x) return a.x > b.x;
if (a.y != b.y) return a.y > b.y;
return a.z > b.z;
} bool cmp2(student a, student b){
if (a.y != b.y) return a.y > b.y;
if (a.z != b.z) return a.z > b.z;
return a.x > b.x;
} inline int max(int a, int b, int c){
return max(a, max(b, c));
} inline int lowbit(int k) {
return k & (-k);
} void add(int x, int val){
for (int i=x; i<=maximum; i+=lowbit(i))
bit[i] += val;
return ;
} int query(int x){
int ans = 0;
for (int i=x; i; i-=lowbit(i))
ans += bit[i];
return ans;
} // 分治闭区间[L,R]
void cdq(int l, int r){
if (l >= r || L[r] == L[l]) return ;
int mid = L[(l + r) >> 1];
if (arr[mid].x == arr[mid+1].x) mid--;
if (mid < l) {
// 往右边寻找中点
mid = R[(l + r) >> 1];
if (mid + 1 > r) return ;
}
cdq(l, mid); cdq(mid+1, r);
sort(arr+l, arr+mid+1, cmp2);
sort(arr+mid+1, arr+r+1, cmp2);
int j = l;
for (int i=mid+1; i<=r; i++){
while (j <= mid && arr[j].y > arr[i].y){
add(arr[j].z, arr[j].val);
j++;
}
arr[i].ans += query(maximum) - query(arr[i].z);
}
// 恢复树状数组
for (int i=l; i<j; i++)
add(arr[i].z, -arr[i].val);
return ;
}

【题解】A18747.眼红的同学的更多相关文章

  1. 【FCS NOI2018】福建省冬摸鱼笔记 day6【FJOI 2018】福建省选混分滚蛋记 day1

    记录一下day6发生的事情吧. 7:30 到达附中求索碑,被人膜,掉RP. 7:50 进考场,6楼的最后一排的最左边的位置,世界上最角落的地方,没有任何想法. 发现电脑时间和别人不一样,赶快调了一下. ...

  2. USACO 1.4.2 Mother's Mil 母亲的牛奶(DFS)

    Description 农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,最初,A和B桶都是空的,而C桶是装满牛奶的.有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装 ...

  3. codevs——1842 递归第一次

    1842 递归第一次  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题解       题目描述 Description 同学们在做题时常遇到这种函数 f( ...

  4. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  5. NOIP 2008提高组第三题题解by rLq

    啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...

  6. [题解]扫雷Mine

    // 此博文为迁移而来,写于2015年2月6日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vrft.html 1088 ...

  7. BZOJ 4247: 挂饰 题解

    Description JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上. JOI君的挂饰有一些与众不同--其中的一些挂饰附有可以挂其他挂件的挂钩.每个挂件要么直 ...

  8. noip2008普及组3题题解-rLq

    (第一次写题解,随意喷) (只是前一天的作业哈) (先凑个数) 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏.游戏规则是这样的:n个同学站成一个圆圈 ...

  9. NOIP2008普及组题解

    NOIP2008普及组题解 从我在其他站的博客直接搬过来的 posted @ 2016-04-16 01:11 然后我又搬回博客园了233333 posted @ 2016-06-05 19:19 T ...

  10. HDU 2023题解分析

    我想说这道题我还没弄明白我错哪了,交了20多遍一直都是Runtime Error,改了N次还是不对,后来搜了一下,说是数组开小了,又把数组开大,还不对,又改发现一个平均值求错,再改,还不对,洗洗睡吧. ...

随机推荐

  1. std::thread 二:互斥量(lock() & unlock())

    mutex  互斥量的作用是保护共享数据 *:有 lock()  就一定要有  unlock() #include <iostream> #include <thread> # ...

  2. SSH的密码qsnctfwp

    开启 kali,在终端输入ssh root@challenge.qsnctf.com -p [port]可以访问远程 SSH 系统 根据提供的 passlist.txt 文件内容进行密码爆破 编写 S ...

  3. mysql 必知必会整理—数据插入和更新还有删除[十]

    前言 简单整理数据插入更新还有删除. 正文 插入: INSERT INTO customers( customers.cust_address, customers.cust_city, custom ...

  4. xml转voc,voc转coco,coco转yolo,coco划分,coco检查,yolo检查,coco可视化

    平常用coco格式的数据集比较多,所有这里整合一下数据集相关的常用的脚本. pycocotools安装 这个非常重要,因为处理coco数据集时,用pycocotools包非常方便. 自行搜索一下怎么安 ...

  5. leetcode:655. 输出二叉树

    655. 输出二叉树 在一个 m*n 的二维字符串数组中输出二叉树,并遵守以下规则: 1> 行数 m 应当等于给定二叉树的高度. 2> 列数 n 应当总是奇数. 3> 根节点的值(以 ...

  6. WPF开发随笔收录-获取程序专有内存

    分享一个C#获取程序当前所占用的内存大小的方法,实测跟任务管理器上的内存值一样 /// <summary> /// 性能计数器组件类 /// </summary> privat ...

  7. 数据分布算法:hash+ 一致性 hash + redis cluster 的 hash slot

    讲解分布式数据存储的核心算法,数据分布的算法 hash 算法 -> 一致性 hash 算法(memcached) -> redis cluster 的 hash slot 算法 用不同的算 ...

  8. 说说对 Node 中的 Buffer 的理解?应用场景?

    一.是什么 在Node应用中,需要处理网络协议.操作数据库.处理图片.接收上传文件等,在网络流和文件的操作中,要处理大量二进制数据,而Buffer就是在内存中开辟一片区域(初次初始化为8KB),用来存 ...

  9. SnakeYaml反序列化分析

    前言 SnakeYaml是Java中解析yaml的库,而yaml是一种人类可读的数据序列化语言,通常用于编写配置文件等.yaml真是到哪都有啊. 环境搭建 <dependency> < ...

  10. ASP.NET Core Web API下基于Keycloak的多租户用户授权的实现

    在上文<Keycloak中授权的实现>中,以一个实际案例介绍了Keycloak中用户授权的设置方法.现在回顾一下这个案例: 服务供应商(Service Provider)发布/Weathe ...