题目:http://acm.hdu.edu.cn/showproblem.php?pid=2852
题意:三种操作:
0 插入
1 删除
2 查找比a大的第k个数。
思路:看了大神都是用树状数组写的,自己也便去学了树状数组
什么是树状数组?
树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值。
  树状数组十分容易实现,代码量小,时间复杂度低,并且经过数学处理后也可以实现成段更新。线段树也可以做到和树状数组一样的效果,但是代码要复杂得多。不过要注意,一般情况下树状数组能解决的问题线段树都能解决,反之有些线段树能解决的问题树状数组却不行。
  
  令这棵树的结点编号为C1,C2…Cn。令每个结点的值为这棵树的值的总和,那么容易发现
C1 = A1
C2 = A1 + A2
C3 = A3
C4 = A1 + A2 + A3 + A4
C5 = A5
C6 = A5 + A6
C7 = A7
C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
如果要求 a[1] ~ a[7] 的和,即为 C[7] + C[6] + C[4] ,如果要改变 a[1] 的值,改变C数组中和 a[1] 有关的项即可(即 C[1] C[2]C[4] C[8])。 这就是树状数组!实现了O(logn)的查询和删改。

这里有一个有趣的性质:设节点编号为x,那么这个节点管辖的区间为 2^k(其中k为x二进制末尾0的个数)个元素。因为这个区间最后一个元素必然为Ax,所以很明显:Cn = A(n – 2^k + 1) + … + An,算这个2^k有一个快捷的办法,定义一个函数如下即可(求解2^k即求二进制码右边第一位1的值):
int lowbit(int x) {
return x & (-x);
}
当想要查询一个SUM(n)(求a[1]~a[n]的),可以依据如下算法即可:

令sum = 0,转第二步;
假如n <= 0,算法结束,返回sum值,否则sum = sum + Cn,转第三步;
令n = n – lowbit(n),转第二步。
可以看出,这个算法就是将这一个个区间的和全部加起来。

那么修改呢,修改一个节点,必须修改其所有祖先,最坏情况下为修改第一个元素,最多有log(n)的祖先。所以修改算法如下(给某个结点i加上x):

当i > n时,算法结束,否则转第二步;
Ci = Ci + x, i = i + lowbit(i)转第一步。i = i + lowbit(i)这个过程实际上也只是一个把末尾1补为0的过程。 对于数组求和来说树状数组简直太快了!

树状数组基本模板

#include <stdio.h>
#define N 100
int a[N];//原数组,从1开始
int c[N];//树状数组,从1开始
int n;//数组的实际数据的大小
int lowbit(int i) //取右边第一次出现1的位数,如10100,则取100, 11则取1
{
//原理:拿一个正数来说,它对应的负数在计算机中用补码表示方式为:从低位到高位,第一个出现1以后,0变1,1变0.
// 那么这个数和它的负数在计算机中的表示正好从低位到高位第一个1出现之前,都是一样的,之后每一位正好想法,&
//操作后,正好取到了要取的那几位
return i&(-i);
}
void modify(int pos, int num) //a是原数组,当a[pos]增加num时,树状数组相应的变化
{
while (pos <= n) {
c[pos] += num;
pos += lowbit(pos);
}
}
void getResult(int pos) //计算a[1]-a[pos]的和
{
//比如计算a[1]~a[6]的和,首先c[6]肯定是xx到a[6]的和,6是0110, lowbit是10, 所以c[6]对应的是0101~0110
//的和,即a[6]+a[5]计算了后两位,还剩下0110-10(pos-lowbit(pos)), 下面要算0100, a[1]~a[4]的和c[4]肯
//定是xx到a[4]的和,0100的lowbit是100, 所以c[4]对应的是0001~0100的和,即a[1]+..+a[4]a[1]~a[6]的和已
//经全部算出了
int sum = 0;
while (pos ) {
sum += c[pos];
pos -= lowbit(pos);
}
return sum;
}
void init()//初始化树状数组
{
int i;
scanf("%d", &n);
for (i=1; i<=n; i++)
{
scanf("%d", &a[i]);
modify(i, a[i])
}
}

本题中0 1 操作都好进行,我们令数组a 下角标为数据的值,初始化都为0,插入a的值为1,删除a为-1,.所以0<角标<100000,进行操作2时,就是查找a到100000中有没有值大于等于sum(a)+k,d的数组的角标存在。对于数据大,有序排列的数,可以用二分法查找。

#include <stdio.h>
#include <string.h> int C[100005]; int lowbit(int k)
{
return k & (-k);
} int sum(int x)
{
int ans = 0;
while (x > 0)
{
ans += C[x];
x -= lowbit(x);
}
return ans;
} void add(int nn, int val)
{
while (nn <= 100000)
{
C[nn] += val;
nn += lowbit(nn);
}
} void search(int a, int k)//金典 二分法
{
int L = a, r = 100000, mi;
int now = sum(a);
while (L < r)
{
int mid = (L+r)/2;
mi = sum(mid);
if (mi < now + k)
L = mid + 1;
else
r = mid;
}
if (sum(L)>= now + k)
printf("%d\n", L);
else
printf("Not Find!\n");
}
int main()
{
int n;
while (scanf("%d", &n)!=EOF)
{
memset(C, 0, sizeof C);
int p, aa, kk;
while (n--)
{
scanf("%d%d", &p, &aa);
if (p == 0)
{
add(aa, 1);
}
else if (p == 1)
{
if (sum(aa) - sum(aa-1) == 0)
printf("No Elment!\n");
else add(aa, -1);
}
else
{
scanf("%d", &kk);
search(aa, kk);
}
}
}
}

2852 ACM 杭电 KiKi's K-Number 0 1 2的更多相关文章

  1. ACM 杭电HDU 2084 数塔 [解题报告]

    数塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...

  2. 2554 ACM 杭电 数学

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2554 中文题目,题意易懂.但是本题涉及到很强的数学思维. 思路:看了题意后:我的第一反应是除了 n=1,n ...

  3. 2159 ACM 杭电 杀怪 二维费用的背包+完全背包问题

    题意:已知经验值,保留的忍耐度,怪的种数和最多的杀怪数.求进入下一级的最优方案. 思路:用二维费用的背包+完全背包问题 (顺序循环)方法求解 什么是二维费用的背包问题? 问题: 二维费用的背包问题是指 ...

  4. 1013 ACM 杭电 root

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1013 题意:求两个数的根 如: 12->3,99->9,80->8 注意题目没有限制数的 ...

  5. 5410 ACM 杭电 01+完全背包

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5410 虽然是英文题目:但还是很好理解的.明显的背包问题 思路:如果你能想到把题目拆分成小问题,就会简单许多 ...

  6. 2002 ACM 杭电 计算球体积

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2002 注意,要用double 才能过,float过不了. 体积公式要加括号(优先级别)(4 * Π * r ...

  7. 补 第三场多校杭电 费用流 K Subsequence

    K Subsequence 这个题目是这个人想吃东西,但是他每次吃的都是他的美味值都必须不递减,可以吃k次,问这个最大的美味值是多少. 这个是一个比较明显的费用流,建图也很好建,但是呢,这个题目卡sp ...

  8. 2602 ACM 杭电 骨头容器 01背包

    题意:装骨头的容器大小固定,有一堆骨头,已知骨头的价值和大小,在不超过容积大小的情况下,问:所装骨头的最大价值? 思路:典型的01背包问题,不需要有任何的变动. 模板: for(int j=v;j&g ...

  9. 2955 ACM 杭电 抢银行 01背包 乘法

    题意: 强盗抢银行,在不被抓住的情况下,想尽量多的偷点钱.已知各个银行的金钱和被抓的概率,以及强盗能容忍的最大不被抓的概率(小于等于该概率才能不被抓),求最多能抢到钱? 并不是简单的01背包问题? 1 ...

随机推荐

  1. Libevent源码分析—event_add()

    接下来就是将已经初始化的event注册到libevent的事件链表上,通过event_add()来实现,源码位于event.c中. event_add() 这个函数主要完成了下面几件事: 1.将eve ...

  2. 【转】如何安装JDK以及配置Java运行环境

    具体的参考这篇博文就好了~~!http://www.cnblogs.com/liu-en-ci/p/6743106.html

  3. centos配置golang & SVN客户端配置

    环境:centos 6.5 一.下载和解压go环境包 >>cd /usr/local/ >>wget -c http://golangtc.com/static/go/go1. ...

  4. 转载:configure生成的文件(1.5.3)《深入理解Nginx》(陶辉)

    原文:https://book.2cto.com/201304/19620.html 当configure执行成功时会生成objs目录,并在该目录下产生以下目录和文件:|---ngx_auto_hea ...

  5. mysql 常用,使用经验

    mysql default  boolean字段 `enable` char(1) NOT NULL DEFAULT '1' COMMENT '启(禁)用',结果: this.enable ? &qu ...

  6. 基于Golang设计一套微服务架构[转]

      article- @嘟嘟噜- May/26/2018 18:35:30 如何基于Golang设计一套微服务架构 微服务(Microservices),这个近几年我们经常听到.那么现在市面上的的微服 ...

  7. php反射类的使用及Laravel对反射的使用介绍

    PHP的反射类与实例化对象作用相反,实例化是调用封装类中的方法.成员,而反射类则是拆封类中的所有方法.成员变量,并包括私有方法等.就如“解刨”一样,我们可以调用任何关键字修饰的方法.成员.当然在正常业 ...

  8. jquery----用户密码验证

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. hdu2838树状数组解逆序

    离散化和排序后的序号问题搞得我实在是头痛 不过树状数组解逆序和偏序一类问题真的好用 更新:hdu的数据弱的真实,我交上去错的代价也对了.. 下面的代码是错的 /* 每个点的贡献度=权值*在这个点之前的 ...

  10. 用PNChart绘制饼状图简介

    写在前面 最近做的小Demo中有一个绘制饼状图的需求.在开始实现之前上网了解了一下现有的一些绘制图形的第三方库,相应的库还是有挺多的,PNChart便是其中一个.PNChart是一个90后的中国boy ...