题目: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. windows环境变量PATH顺序的重要性

    PATH是路径的意思,PATH环境变量中存放的值,就是一连串的路径.不同的路径之间,用英文的分号间隔开.系统在执行用户命令时,若用户未给出绝对路径,则首先在当前目录下寻找相应的可执行文件.批处理文件等 ...

  2. scn 时间

    Scn转换成时间: select to_char(scn_to_timestamp(3998591352171),'YYYY-MM-DD HH24:MI:SS') from dual: 时间转换成sc ...

  3. centos系统设置通过windows代理上网

    网络环境说明: 物理机windows xp sp3系统 ip:192.168.29.21(通过路由上网,有权限设置proxy给其他机器代理上网) 虚拟机centos5.5系统 ip:192.168.2 ...

  4. HTML常用特殊字符

    网页特殊符号HTML代码大全   HTML特殊字符编码大全:往网页中输入特殊字符,需在html代码中加入以&开头的字母组合或以&#开头的数字.下面就是以字母或数字表示的特殊符号大全. ...

  5. 随机森林学习-2-sklearn

    # -*- coding: utf-8 -*- """ RandomForestClassifier skleran的9个模型在3份数据上的使用. 1. 知识点: skl ...

  6. C#控制台中创建数据库连接

    与数据库的连接主要有以下三种类: sqlconnection:数据库连接类: sqlcommand:数据库操作: sqldatareader:数据库读取: SqlDataReader dr = cmd ...

  7. lr使用linux Generator测试https莫名报 SSL protocol error when attempting to connect with host

    接收一个性能测试任务,各种原因需要使用linux agent产生压力.诡异的事发生了,同样脚本windows回放成功,使用linux agent报如下错误,脚本回放失败. Action.c(33): ...

  8. LeetCode(8):字符串转整数(atoi)

    Medium! 题目描述: 实现 atoi,将字符串转为整数. 在找到第一个非空字符之前,需要移除掉字符串中的空格字符.如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合 ...

  9. linux 终端上网设置

    原网址: https://www.aliyun.com/jiaocheng/215068.html 摘要:第一步,需要安装一个名为w3m的软件工具,打开终端,输入如下命令sudoapt-getinst ...

  10. PHP中嵌套函数被调用时出现报错的问题

    对于初入门的PHP新手来说,在学习关于PHP函数嵌套的知识点时可能会有一定的难度.比如有的朋友在练习PHP函数嵌套相关问题时,会遇到调用内部函数时就会出现报错的情况等. 那么本篇文章就为大家详细得分析 ...