Codeforces300 F. A Heap of Heaps
出处: Codeforces
主要算法:树状数组/线段树
难度:4.6
思路分析:
在没看到数据范围之前真是喜出望外,直到发现O(n^2)会被卡……
其实也不是特别难的
我们要做的事情就是对于每一个节点v,求出当k分别取\(1,2,3,...,n\)时比v的权值小的v的儿子数量。既然要求每个节点的,那n自然是要扫的。那有没有能够在O(log n)复杂度内求出权值小于v的节点数量的方法呢?这自然让我们联想到了O(log n)的数据结构——树状数组或者线段树。
数组a[i]保存节点的信息。a[i].x表示权值,a[i].idx表示编号(位置)。首先将数组a按照x从小到大进行排序,并在处理好每一个节点后用树状数组更新bit[a[i].idx],让它+1。bit[i]维护的其实就是位置i是否被更新过。那么设想一下,因为a数组是按照权值进行排序的,所以已经被更新过的点的权值一定<=a[i]。因此我们可以查询区间[left,right](表示节点v的子节点的位置的左右位置的最值),得到的答案就是小于节点v权值的子节点的数量。而由于此序列是一定的,无论k怎么变,只需要改变一下left和right就可以得到不同的堆的答案了。所以我们进行如下操作:
\(ans[k] += Query(right) - Query(left-1);\)
我想意义已经很清楚了。
最后有一个复杂度的计算问题:我在外层扫描了节点i,内层扫描了堆的叉数k,又做了bit,为什么复杂度会是\(O(n log n)\)?不应该是\(O(n^2 log n)\)吗?但是总共就n个节点,并且k越大叶子就越多,所以到后来几乎一进循环就会跳出。所以复杂度就等同于\(O(n)\)了
代码注意点:
排序改成双关键字。因为要先更新父亲,再更新儿子。不然与父亲节点权值相同的儿子会被算为违反的。
Code
/*By QiXingzhi*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int N = ;
const int INF = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x << ) +(x << ) + c - '', c = getchar();
return x * w;
}
struct Number{
int x,idx;
}a[N];
int n,m,left,right;
int bit[N],ans[N];
inline bool comp(Number& a, Number& b){
if(a.x == b.x) return a.idx < b.idx;
return a.x < b.x;
}
inline int GetLeft(int v, int k){
return (k * (v-) + );
}
inline int GetRight(int v, int k){
return ((k * v) + );
}
inline int Query(int x){
int i = x;
int res = ;
while(i > ){
res += bit[i];
i -= i & (-i);
}
return res;
}
inline void Update(int x, int k){
int i = x;
while(i <= N){
bit[i] += k;
i += i & (-i);
}
}
int main(){
n = r;
for(int i = ; i <= n; ++i){
a[i].x = r;
a[i].idx = i;
}
sort(a+,a+n+,comp);
for(int i = ; i <= n; ++i){
for(int k = ; k < n; ++k){
left = GetLeft(a[i].idx,k);
right = GetRight(a[i].idx,k);
if(left > n) break;
if(right > n) right = n;
ans[k] += Query(right) - Query(left-);
}
Update(a[i].idx, );
}
for(int i = ; i < n; ++i){
printf("%d ", ans[i]);
}
return ;
}
Codeforces300 F. A Heap of Heaps的更多相关文章
- Codeforces Round #300 F - A Heap of Heaps (树状数组 OR 差分)
F. A Heap of Heaps time limit per test 3 seconds memory limit per test 512 megabytes input standard ...
- Codeforces 538 F. A Heap of Heaps
\(>Codeforces \space 538 F. A Heap of Heaps<\) 题目大意 :给出 \(n\) 个点,编号为 \(1 - n\) ,每个点有点权,将这些点构建成 ...
- [codeforces538F]A Heap of Heaps
[codeforces538F]A Heap of Heaps 试题描述 Andrew skipped lessons on the subject 'Algorithms and Data Stru ...
- L - A Heap of Heaps CodeForces - 538F 主席树
L - A Heap of Heaps CodeForces - 538F 这个是一个还比较裸的静态主席树. 这个题目的意思是把这个数组变成k叉树,然后问构成的树的子树小于等于它的父节点的对数有多少. ...
- Codeforces538F A Heap of Heaps(函数式线段树)
题意:给你一个数组a[n],对于数组每次建立一个完全k叉树,对于每个节点,如果父节点的值比这个节点的值大,那么就是一个违规点,统计出1~n-1完全叉树下的违规点的各自的个数. 一个直觉的思想就是暴力, ...
- CodeForces 538F A Heap of Heaps
题意 给定一个长度为n的数组A,将它变为一颗k叉树(1 <= k <= n - 1)(堆的形式编号). 问对于每一个k,有多少个节点小于它的父节点. 解题 显然,最初的想法是暴力.因为树的 ...
- [CF538F]A Heap of Heaps(主席树)
题面 题意:给你一个数组a[n],对于数组每次建立一个完全k叉树,对于每个节点,如果父节点的值比这个节点的值大,那么就是一个违规点,统计出1~n-1完全叉树下的违规点的各自的个数. 分析 注意到完全k ...
- Codeforces Round #300 解题报告
呜呜周日的时候手感一直很好 代码一般都是一遍过编译一遍过样例 做CF的时候前三题也都是一遍过Pretest没想着去检查... 期间姐姐提醒说有Announcement也自信不去看 呜呜然后就FST了 ...
- CF数据结构练习
1. CF 438D The Child and Sequence 大意: n元素序列, m个操作: 1,询问区间和. 2,区间对m取模. 3,单点修改 维护最大值, 取模时暴力对所有>m的数取 ...
随机推荐
- Pytest+Allure定制报告
前言: 最近在研究接口自动化的框架,好的测试报告在整个测试框架起到至关重要的部分.终于被我发现一个超好用的报告框架,不仅报告美观,而且方便CI集成. 就是它,就是它:Allure Test Repor ...
- super关键字访问父类成员
1.super只能出现在子类的方法和构造方法中: 2.super调用构造方法时只能是第一句: 3.super不能访问父类的private成员.
- 埋锅。。。BZOJ1004-置换群+burnside定理+
看这道题时当时觉得懵逼...这玩意完全看不懂啊...什么burnside...难受... 于是去看了点视频和资料,大概懂了置换群和burnside定理,亦步亦趋的懂了别人的代码,然后慢慢的打了出来.. ...
- PS制作墙壁上海报卷页图片效果
1.首先,打开PS,新建合适的画布. 2.为了使背景具有质感,执行滤镜—滤镜库—纹理化,具体参数按你的感觉来. 3.新建画布“图层1”,为了方便观察,填充为灰色画布,ctrl+t适当缩小画布大小,如图 ...
- python模块详解
什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码(.p ...
- PAT L2-007 家庭房产
https://pintia.cn/problem-sets/994805046380707840/problems/994805068539215872 给定每个人的家庭成员和其自己名下的房产,请你 ...
- composer 自动加载类 通过psr
项目地址 git@github.com:brady-wang/composer.git "autoload":{ "classmap":[ "Lib ...
- ssm项目跨域访问
最近使用ssm开发了一个项目,为了项目的开发速度,采用的是前后端同时开发,所以前端文件没有集成在项目中,最后在调试时涉及到了跨域.跨域的解决方法很多,我采用的是最简单的一种,代码如下: 新建一个过滤器 ...
- 在linux上安装Scala详细步骤
scala在linux安装很简单,就是下载,解压,配置环境变量,source一下成功. 提君博客原创 >>提君博客原创 http://www.cnblogs.com/tijun/ < ...
- hive数学函数
round 四舍五入 ceil向上 取整 floor向下取整 hive > select floor(45.8); ok 45