题意:给你一个数组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. android版本vqmon移植IOS版

    IOS交叉编译 1.android版本 vqmon已经正常运行,现需要开放IOS版本,作移植工作. 2. 注意事项: 1)ROOT权限,IOS必须越狱.  2)依赖库:pcap, ffmpeg,lib ...

  2. 不作伪分享者决定完整分享我自学Python3的全部过程细节

    不作伪分享者决定完整分享我自学Python3的全部过程细节   我不要作伪分享者 十六年前我第一次见到了电脑,并深深地爱上了它: 十二年前我第一次连上了网络,并紧紧地被它爱上. 十年前的网络是田园美景 ...

  3. CodeSimth - .Net Framework Data Provider 可能没有安装。解决方法[转载 ]

    原文:http://www.cnblogs.com/chenrui7/p/3592082.html 今天想使用CodeSimth生成一个sqlite数据库的模板.当添加添加数据库的时候发现: .Net ...

  4. linux socket c/s上传文件

    这是上传文件的一个示例,可以参照自行修改成下载或者其它功能. 在上传时,需要先将文件名传到服务器端,这是采用一个结构体,包含文件名及文件名长度(可以用于校验),防止文件名乱码. client #inc ...

  5. 网络--路由表&IP选路

    路由表的 flags 字段显示路由状态: A 活动的休眠网关检测在路由上被启用.本字段只适用于 AIX 5.1 或更新版本. U :Up. H :路由至主机而不是网络. G :路由至网关. 不带G表示 ...

  6. 爬虫:Scrapy7 - Scrapy终端(Scrapy shell)

    Scrapy 终端是一个交互终端,可以在未启动 spider 的情况下尝试及调试你的爬取代码.其本意是用来测试提取数据的代码,不过可以将其作为正常的 Python 终端,在上面测试任何 Python ...

  7. ArcGIS 创建要素时提示“表已经被注册(table already registered)”

    今天一位实施大哥在ArcCatalog中要重建一个要素类,所以就在ArcCatalog中连接上Oracle数据库,直接删除了要素类,然后重新创建了一个新的要素类,可是却报错“表已经被创建”,并提示不可 ...

  8. springmvc和struts2的区别(转)

    1.客户端浏览器发出HTTP请求.   2.根据web.xml配置,该请求被FilterDispatcher接收.   3.根据struts.xml配置,找到需要调用的Action类和方法, 并通过I ...

  9. [洛谷P2216][HAOI2007]理想的正方形

    题目大意:有一个$a\times b$的矩阵,求一个$n\times n$的矩阵,使该区域中的极差最小. 题解:二维$ST$表,每一个点试一下是不是左上角就行了 卡点:1.用了一份考试时候写的二维$S ...

  10. [codeforces] 585D Lizard Era: Beginning || 双向dfs

    原题 有n(n<=2)个任务和三个人,每次任务给出每个人能得到的值,每次任务选两个人,使n个任务结束后三个人得到的值是一样的.输出每次要派哪两个人,如果不行输出Impossible. n< ...