题目链接:眼红的同学

题干信息很简单,看到数据量之后就不简单了。在数据量小的时候可以使用双层循环暴力的方法来求答案。显然对于这道题而言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. Python 集合(Sets)3

    Python - 合并集合 在 Python 中,有几种方法可以合并两个或多个集合.您可以使用union()方法,该方法返回一个包含两个集合中所有项的新集合,或使用update()方法,将一个集合中的 ...

  2. Matplotlib绘图设置---文字和标签

    文字和文字位置 通过plt.text()或ax.text()命令可在图形上添加文字. Signature: ax.text(x, y, s, fontdict=None, withdash=<d ...

  3. C++执行Linux命令

    一.执行简单命令 比如需要创建文件.文件夹.删除文件 #include <iostream> #include <stdio.h> #include <stdlib.h& ...

  4. Python生成测试数据--Faker的使用方法

    # 官方文档:https://faker.readthedocs.io/en/master/index.html # 安装:pip install Faker from faker import Fa ...

  5. Native Rawfile开发指导

      场景介绍 开发者可以通过本指导了解在HarmonyOS应用中,如何使用Native Rawfile接口操作Rawfile目录和文件.功能包括遍历.打开.搜索.读取和关闭Rawfile. 接口说明 ...

  6. js es6 delete

    前言 首先delete 不同于nodejs delete,看下有什么不同. 正文 var test=5; delete test; console.log(test); 结果是test没有受到任何影响 ...

  7. Django框架——ajax补充、多对多三种创建、序列化组件、批量操作数据、分页器

    ajax补充说明 主要是针对回调函数args接收到的响应数据 1.后端request.is_ajax() 用于判断当前请求是否由ajax发出 2.后端返回的三板斧都会被args接收不再影响整个浏览器页 ...

  8. 【数学】向量点乘、叉乘的理论、应用及代码实现(C++)

    前言 我总结了一下向量点乘,叉乘的概念,以及他们的应用及相关C++代码的实现.blog 这类问题也是技术面试经常碰到的,一次研究透了会有收获. 1 向量 向量具有大小和方向. 共线向量:两个平行的向量 ...

  9. 力扣118(java)-杨辉三角(简单)

    题目: 给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行. 在「杨辉三角」中,每个数是它左上方和右上方的数的和. 示例 1: 输入: numRows = 5输出: [[1], ...

  10. 力扣599(java&python)- 两个列表的最小索引总和(简单)

    题目: 假设 Andy 和 Doris 想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示. 你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅. 如果答案不止一 ...