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小值 详解——替罪羊套函数式线段树
不得不说,做过最爽的树套树———— 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...
随机推荐
- [bzoj3371][poj2009][Usaco2004 Mar]Moo University - Emergency Pizza Order 定制比萨饼
标题这么长的..真是让感觉人头大脚轻. 贴题面先. Description Moo大学的餐厅必须为$C(1\leq C\leq 1000)$头入学的奶牛新生定制比萨饼.比萨饼可以在比萨小屋订做 ...
- 获取HTTP请求头中的地址
技术交流群:233513714 public static String getIpAddr(HttpServletRequest request) { String ip = request.get ...
- 洛谷P1605 迷宫
迷宫 题目链接 这道题就是一道简单的dfs计方案数qwq. 我的思路是把表初始化为1,再将障碍改为0,因为在全局定义中数组会直接初始化为0,所以就少去了对边界的特判. next数组加循环可以减少代码量 ...
- eclipse、myeclipse 反编译插件 轻松查看源代码
java反编译插件:Eclipse Class Decompiler,能够很方便的使用本插件查看类库源码,以及采用本插件进行Debug调试. eclipse中安装Eclipse Class Decom ...
- DOS程序员手册(二)
2.6存储设备 随着DOS的升级,磁盘存储容量也有了很大扩充.表2.4介绍了软盘容量的增加以 及所支持驱动器型号的数量. ...
- 那些牛掰的 HTML5的API(二)
1:视频播放器 2:地理定位 我们的支持html5 的浏览器给我们提供一个接口(api),可以用来获取你当前的位置. 主要是通过geolocation(地理位置),对象 ,去访问硬件,来获取到经纬度. ...
- hexo站点地图
将网站链接提交到百度 百度搜索引擎提交入口 有三种验证方式,我选择Html标签验证,在themes\next\layout\_partials\head.swing中添加验证代码: <meta ...
- 【bzoj4822/bzoj1935】[Cqoi2017]老C的任务/[Shoi2007]Tree 园丁的烦恼 树状数组
原文地址:http://www.cnblogs.com/GXZlegend/p/6825530.html bzoj4822 题目描述 老 C 是个程序员. 最近老 C 从老板那里接到了一个任务 ...
- [poj] 1204 Word Puzzles || AC自动机
原题 给个X*Y的字符串矩阵,W个询问,对每个询问输出这个串出现的位置及方向,共有8个方向,顺时针开始分别用A~H表示 AC自动机的板子题. 对于待匹配串建一个自动机,然后从矩阵的四周分别沿八个方向跑 ...
- BZOJ 1014 [JSOI2008]火星人prefix | Splay维护哈希值
题目: 题解: #include<cstdio> #include<algorithm> #include<cstring> typedef long long l ...