Codeforces题号:#300F

出处: 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的更多相关文章

  1. 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 ...

  2. Codeforces 538 F. A Heap of Heaps

    \(>Codeforces \space 538 F. A Heap of Heaps<\) 题目大意 :给出 \(n\) 个点,编号为 \(1 - n\) ,每个点有点权,将这些点构建成 ...

  3. [codeforces538F]A Heap of Heaps

    [codeforces538F]A Heap of Heaps 试题描述 Andrew skipped lessons on the subject 'Algorithms and Data Stru ...

  4. L - A Heap of Heaps CodeForces - 538F 主席树

    L - A Heap of Heaps CodeForces - 538F 这个是一个还比较裸的静态主席树. 这个题目的意思是把这个数组变成k叉树,然后问构成的树的子树小于等于它的父节点的对数有多少. ...

  5. Codeforces538F A Heap of Heaps(函数式线段树)

    题意:给你一个数组a[n],对于数组每次建立一个完全k叉树,对于每个节点,如果父节点的值比这个节点的值大,那么就是一个违规点,统计出1~n-1完全叉树下的违规点的各自的个数. 一个直觉的思想就是暴力, ...

  6. CodeForces 538F A Heap of Heaps

    题意 给定一个长度为n的数组A,将它变为一颗k叉树(1 <= k <= n - 1)(堆的形式编号). 问对于每一个k,有多少个节点小于它的父节点. 解题 显然,最初的想法是暴力.因为树的 ...

  7. [CF538F]A Heap of Heaps(主席树)

    题面 题意:给你一个数组a[n],对于数组每次建立一个完全k叉树,对于每个节点,如果父节点的值比这个节点的值大,那么就是一个违规点,统计出1~n-1完全叉树下的违规点的各自的个数. 分析 注意到完全k ...

  8. Codeforces Round #300 解题报告

    呜呜周日的时候手感一直很好 代码一般都是一遍过编译一遍过样例 做CF的时候前三题也都是一遍过Pretest没想着去检查... 期间姐姐提醒说有Announcement也自信不去看 呜呜然后就FST了 ...

  9. CF数据结构练习

    1. CF 438D The Child and Sequence 大意: n元素序列, m个操作: 1,询问区间和. 2,区间对m取模. 3,单点修改 维护最大值, 取模时暴力对所有>m的数取 ...

随机推荐

  1. CSS Modules入门教程

    为什么引入CSS Modules 或者可以这么说,CSS Modules为我们解决了什么痛点.针对以往我写网页样式的经验,具体来说可以归纳为以下几点: 全局样式冲突 过程是这样的:你现在有两个模块,分 ...

  2. D2. Great Vova Wall (Version 2)

    l链接 [https://codeforces.com/contest/1092/problem/D2] 题意 和D1一样只是不能竖直放了 分析 水平放的话,就只可能是相邻等时才可以,而且你会发现 只 ...

  3. CF892.B. Wrath

    ---恢复内容开始--- 题意: 有n个犯人,手上都有个长度为Li的武器,当铃响时大家同时挥动武器,只能把前面攻击范围内的敌人杀死,问最后还剩几个人. 题目传送门: [http://codeforce ...

  4. 将iso镜像转换为docker镜像

    为什么不用官方的镜像? 不是不想使用,而是官方镜像提供的功能实在是太少了,不信的话,你pull一个ubuntu:latest的进行,你看有没有wget.curl.ssh这些功能,就连最简单的ifcon ...

  5. ERP & CRM

    ERP流程_百度百科https://baike.baidu.com/item/ERP%E6%B5%81%E7%A8%8B/8099248 CRM_百度百科https://baike.baidu.com ...

  6. CSS响应式布局实例

    <style type="text/css">        body{            margin:0 auto;            min-width: ...

  7. Windows10常用快捷键

    1. 打开注册表 ctrl+R   --->   regedit   2.打开资源管理器 win + E    3.切换到桌面 win + D   再按一次可以进行还原   4.锁屏 win+ ...

  8. java编程规范(持续更新)

    1:非空判断 错误例子: if(user.getUserName().equals("hollis")){ } 这段代码极有可能在实际运行的时候跑出NullPointerExcep ...

  9. Angular 自定义过滤器

    <!DOCTYPE html><html ng-app="myApp"><head lang="en"> <meta ...

  10. Django Rest framework 框架之解析器

    解析器 序列化***** 请求数据进行校验 对queryset进行序列化处理 分页 路由 视图 渲染器