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

一个直觉的思想就是暴力,因为完全k叉树当k很大的时候,其实层数是特别小的,所以感觉暴力是可以的。注意到一个完全k叉树下v节点的儿子的公式是:

k*(v-1)+2...kv+1,相应的父节点的公式是 (v+k-2)/k。儿子的编号是连续的,如果我们可以对每个节点快速的求出连续编号的节点有多少个数比它小我们就可以快速的更新答案了,但是如果对每个节点都这样做的话就至少是一个O(n^2)级别的做法。注意到对于一棵完全k叉树来说,只有内节点才需要统计,叶节点并不需要。而对于一个大小为n的完全k叉树来说,内节点的个数是O(n/k)的,因此总的内节点个数就是n/1+n/2+n/3+...n/n-1,即O(nlogn)。

然后就是单次询问一段连续的区间里有多少个数比v小。这里我没有想到什么好的简便的方法,不过函数式线段树是一个解决方法。root[i]表示的是用a[i]~a[n]的值建立的线段树,当我需要询问某个区间[l,r]的小于等于v的数有多少个数时,只需要query(root[l],1,v)-query(root[r],1,v)即可。空间复杂度是O(nlogn),时间复杂度是单次询问O(logn),最后总的复杂度就是O(nlog^2 n)

#pragma warning(disable:4996)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
using namespace std; #define maxn 200500
#define maxc maxn*20 int n;
int a[maxn], b[maxn];
int res[maxn];
int root[maxn];
int nsize; int lc[maxc], rc[maxc];
int sum[maxc];
int tot; int insert(int rt, int L, int R, int v)
{
int cur = tot++;
if (L == R){
sum[cur] = sum[rt] + 1;
return cur;
}
int M = (L + R) >> 1;
if (v <= M){
rc[cur] = rc[rt];
lc[cur] = insert(lc[rt], L, M, v);
}
else{
lc[cur] = lc[rt];
rc[cur] = insert(rc[rt], M + 1, R, v);
}
sum[cur] = sum[lc[cur]] + sum[rc[cur]];
return cur;
} int query(int rt, int L, int R, int l, int r)
{
if (l == L&&r == R){
return sum[rt];
}
int M = (L + R) >> 1;
if (r <= M){
return query(lc[rt], L, M, l, r);
}
else if (l>M){
return query(rc[rt], M + 1, R, l, r);
}
else{
return query(lc[rt], L, M, l, M) + query(rc[rt], M + 1, R, M + 1, r);
}
} int main()
{
while (cin >> n)
{
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
b[i] = a[i];
}
sort(b+1, b + n+1);
nsize = unique(b+1, b + n+1) - b;
for (int i = 1; i <= n; ++i){
a[i] = lower_bound(b + 1, b + nsize, a[i]) - b + 1;
}
memset(res, 0, sizeof(res));
tot = 1;
root[n + 1] = tot;
lc[tot] = rc[tot] = sum[tot] = 0;
tot++;
for (int i = n; i >= 1; i--){
root[i] = insert(root[i + 1], 1, nsize, a[i]);
}
for (int k = 1; k <= n - 1; ++k){
int maxBound = (n + k - 2) / k;
for (int v = 1; v <= maxBound; ++v){
int cnt = 0;
int lbound = k*(v - 1) + 2;
int rbound = min(k*v + 1, n);
cnt = query(root[lbound], 1, nsize, 1, a[v] - 1)- query(root[rbound+1], 1, nsize, 1, a[v] - 1);
res[k] += cnt;
}
}
for (int i = 1; i <= n - 1; ++i){
if (i > 1) printf(" ");
printf("%d", res[i]);
}
puts("");
}
return 0;
}

Codeforces538F A Heap of Heaps(函数式线段树)的更多相关文章

  1. [codeforces538F]A Heap of Heaps

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

  2. 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))

    函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...

  3. POJ2104 K-th number 函数式线段树

    很久没打代码了,不知道为什么,昨天考岭南文化之前突然开始思考起这个问题来,这个问题据说有很多种方法,划分树什么的,不过对于我现在这种水平还是用熟悉的线段树做比较好.这到题今年8月份的时候曾经做过,那个 ...

  4. BZOJ 3123 森林(函数式线段树)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...

  5. BZOJ 3207 花神的嘲讽计划Ⅰ(函数式线段树)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3207 题意:给出一个数列,若干询问.每个询问查询[L,R]区间内是否存在某个长度为K的子 ...

  6. [Usaco2014 Open Gold ]Cow Optics (树状数组+扫描线/函数式线段树)

    这道题一上手就知道怎么做了= = 直接求出原光路和从目标点出发的光路,求这些光路的交点就行了 然后用树状数组+扫描线或函数式线段树就能过了= = 大量的离散+模拟+二分什么的特别恶心,考试的时候是想到 ...

  7. hdu 5111 树链剖分加函数式线段树

    这题说的是给了两棵树,各有100000 个节点,然后Q个操作Q<=50000; 每个操作L1 R1 L2 R2.因为对于每棵树都有一个与本棵树其他点与众不同的值, 最后问 在树上从L1到R1这条 ...

  8. BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 418   Solved: 235 [ Submit][ ...

  9. 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树

    不得不说,做过最爽的树套树———— 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...

随机推荐

  1. SQL语句知识点

    PERSON表 NUMBER NAME SEX AGE 1 THERON male 19 2 JACK male 20 3 LUCY female 20 1.SELECT选择     SELECT 列 ...

  2. hadoop中节点上的nodemanager一直启动不起来

    当我们启动Hadoop集群的时候,发现有一台机器的nodemanager启动后自动关闭, 查看日志的时候发现有错误:yarn-root-nodemanager-log 解决办法: netstat  a ...

  3. 24、php知识点总结基础教程--part-2

    1.表单处理 ①post请求 <html> <body> <form action="welcome.php" method="post&q ...

  4. 【Support Vector Regression】林轩田机器学习技法

    上节课讲了Kernel的技巧如何应用到Logistic Regression中.核心是L2 regularized的error形式的linear model是可以应用Kernel技巧的. 这一节,继续 ...

  5. Java基础-1简单了解与原理

    简单了解: Java看起来设计得很像C++,但是为了使语言小和容易熟悉,设计者们把C++语言中许多可用的特征去掉了,这些特征是一般程序员很少使用的.因为Java没有结构,数组和串都是对象,所以不需要指 ...

  6. 团队项目-第六次Scrum 会议

    时间:11.1 时长:30分钟 地点:F楼2层沙发休息处 工作情况 团队成员 已完成任务 待完成任务 解小锐 完成员工信息的简单初始化 学习cocos creator样例 陈鑫 完成CurrentPr ...

  7. PAT 甲级 1037 Magic Coupon

    https://pintia.cn/problem-sets/994805342720868352/problems/994805451374313472 The magic shop in Mars ...

  8. jquery select chosen禁用某一项option

    $("#tbParBudCode").chosen().change(function () { $("#tbParBudCode option[value='" ...

  9. Python函数参数中的冒号与箭头

    在一些Python的工程项目中,我们会看到函数参数中会有冒号,有的函数后面会跟着一个箭头,你可能会疑惑,这些都是什么东西? 其实函数参数中的冒号是参数的类型建议符,告诉程序员希望传入的实参的类型.函数 ...

  10. What is a Microsoft Failover Cluster Virtual Adapter

    What is a Microsoft Failover Cluster Virtual Adapter anyway? A question often asked is, "What i ...