Codeforces538F A Heap of Heaps(函数式线段树)
题意:给你一个数组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(函数式线段树)的更多相关文章
- [codeforces538F]A Heap of Heaps
[codeforces538F]A Heap of Heaps 试题描述 Andrew skipped lessons on the subject 'Algorithms and Data Stru ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- POJ2104 K-th number 函数式线段树
很久没打代码了,不知道为什么,昨天考岭南文化之前突然开始思考起这个问题来,这个问题据说有很多种方法,划分树什么的,不过对于我现在这种水平还是用熟悉的线段树做比较好.这到题今年8月份的时候曾经做过,那个 ...
- BZOJ 3123 森林(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...
- BZOJ 3207 花神的嘲讽计划Ⅰ(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3207 题意:给出一个数列,若干询问.每个询问查询[L,R]区间内是否存在某个长度为K的子 ...
- [Usaco2014 Open Gold ]Cow Optics (树状数组+扫描线/函数式线段树)
这道题一上手就知道怎么做了= = 直接求出原光路和从目标点出发的光路,求这些光路的交点就行了 然后用树状数组+扫描线或函数式线段树就能过了= = 大量的离散+模拟+二分什么的特别恶心,考试的时候是想到 ...
- hdu 5111 树链剖分加函数式线段树
这题说的是给了两棵树,各有100000 个节点,然后Q个操作Q<=50000; 每个操作L1 R1 L2 R2.因为对于每棵树都有一个与本棵树其他点与众不同的值, 最后问 在树上从L1到R1这条 ...
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
- 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树
不得不说,做过最爽的树套树———— 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...
随机推荐
- 用for循环计算(1-3+5-7...99)的结果(两种方法)
1) sum=0 count=1 for i in range(1,100,2): if count % 2==0: sum = sum - i else: sum = sum + i count = ...
- BZOJ 3027: [Ceoi2004]Sweet
容斥 #include<cstdio> using namespace std; int a,b,n,m[15]; long long ans=0,mod=2004; long long ...
- 以+scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?
这里强调一点:在主线程中以+scheduledTimerWithTimeInterval...的方式触发的timer默认是运行在NSDefaultRunLoopMode模式下的,当滑动页面上的列表时, ...
- Pythonyield使用浅析
转自:https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ 您可能听说过,带有 yield 的函数在 Python ...
- 自动化测试(三)如何用python写个一函数,这个函数的功能是,传入一个数字,产生N条手机号,产生的手机号不能重复
本期时间短没来得及写思路,不过我都加了注释,有问题可以@我 import randomimport timedef Phones(number):#生成手机号函数 s = "01234567 ...
- Python网络编程(OSI模型、网络协议、TCP)
前言: 什么是网络? 网络是由节点和连线构成,表示诸多对象及其相互联系. 在数学上,网络是一种图,一般认为专指加权图. 网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类 型的实际问题中抽象 ...
- 孤荷凌寒自学python第五十一天初次尝试使用python连接Firebase数据库
孤荷凌寒自学python第五十一天初次尝试使用python连接Firebase数据库 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数据库服 ...
- Oz 创建CentOS7镜像
参考链接: https://github.com/clalancette/oz/wiki/Oz-template-description-language https://github.com/cla ...
- CodeSimth - .Net Framework Data Provider 可能没有安装。解决方法[转载 ]
原文:http://www.cnblogs.com/chenrui7/p/3592082.html 今天想使用CodeSimth生成一个sqlite数据库的模板.当添加添加数据库的时候发现: .Net ...
- android DOM解析Xml
文章转自:http://blog.sina.com.cn/s/blog_a661f16c0101d5qp.html People类是自己写的一个类,主要保存各个字符串数据. 由于没学过Xml语法只 ...