利用了二进制,二分的思想的一个很巧妙的数据结构,一个lowbit(x):二进制表示下的最右边的一个1开始对应的数值。

那么如果一个节点的为x左孩子,父亲节点就是 x + lowbit(x),如果是右孩子,父亲节点是 x-lowbit(x);

图中白条部分就是辅助数组C对应的最底下的和。

1、那么一个前缀和有是怎样的呢?

  就是从最底下开始,边往上走,边往左走。

2、修改单点呢?

  从最底下开始,边往上走,边往下走。

LA2191:

题目链接:https://vjudge.net/contest/147973#problem/A

题意:

先给出一个数组,然后有两个操作

S x y 把第x个数改成y

M x y计算x~y个数的和

Source Code:

 #include <bits/stdc++.h>

 using namespace std;

 inline int lowbit(int x)
{
return x&-x;
} struct FenwickTree
{
int n;
vector<int> C; void resize(int n)
{
this->n = n;
C.resize(n+);
}
void clear()
{
fill(C.begin(), C.end(), );
} // 计算A[1]+A[2]+...+A[x] (x<=n)
int sum(int x)
{
int ret = ;
while(x > )
{
ret += C[x];
x -= lowbit(x);
}
return ret;
} // A[x] += d (1<=x<=n)
void add(int x, int d)
{
while(x <= n)
{
C[x] += d;
x += lowbit(x);
}
}
}; FenwickTree f;
const int maxn = +;
int a[maxn]; int main()
{
// freopen("in.txt","r",stdin);
int n;
int cases = ;
while(scanf("%d",&n),n)
{
if(cases>) puts("");
printf("Case %d:\n",++cases);
f.resize(n);
f.clear();
for(int i=; i<=n; i++)
{
scanf("%d",&a[i]);
f.add(i,a[i]);
} char op[];
while(scanf("%s",op)!=EOF)
{
if(!strcmp(op,"END"))
break;
if(op[]=='M')
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",f.sum(y)-f.sum(x-));
}
if(op[]=='S')
{
int x,y;
scanf("%d%d",&x,&y);
int add = y - a[x];
a[x] = y;
f.add(x,add);
}
}
} return ;
}

LA5902:

题目链接:https://vjudge.net/contest/147973#problem/B

题意:

XXX喜欢看电影,他有好多好多的影碟,每个影碟都有个独立的编号。开始是从下往上影碟的顺序是n~1,他每次拿出影碟的时候,你需要输出压在该影碟上的有几个。(拿出后其他影碟顺序不变)看完影碟后,XXX会把影碟放在最上面。

分析:

把每个影碟放到一个考后的位置,这个位置有影碟,那么这里就是 1,否则是 0 ,每次询问,就是这个影碟所在的位置之前的前缀和,

把他放到前面去,当前位置置为 0 ,top 的位置 加 1,注意要记录每个影碟的所在位置。

Source Code:

 #include <bits/stdc++.h>

 using namespace std;

 inline int lowbit(int x)
{
return x&-x;
} struct FenwickTree
{
int n;
vector<int> C; void resize(int n)
{
this->n = n;
C.resize(n);
}
void clear()
{
fill(C.begin(), C.end(), );
} // 计算A[1]+A[2]+...+A[x] (x<=n)
int sum(int x)
{
int ret = ;
while(x > )
{
ret += C[x];
x -= lowbit(x);
}
return ret;
} // A[x] += d (1<=x<=n)
void add(int x, int d)
{
while(x <= n)
{
C[x] += d;
x += lowbit(x);
}
}
}; FenwickTree f;
const int maxn = +;
int pos[maxn]; int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
scanf("%d",&t); while(t--)
{
int n,q;
scanf("%d%d",&n,&q);
f.resize(maxn*);
f.clear(); for(int i=; i<=n; i++)
{
f.add(maxn+i,);
pos[i] = maxn+i;
} int top = maxn;
while(q--)
{
int x;
scanf("%d",&x);
int tmp = pos[x];
if(q!=)
printf("%d ",f.sum(tmp-));
else printf("%d",f.sum(tmp-));
f.add(tmp,-);
f.add(top--,);
pos[x] = top + ;
}
puts("");
}
return ;
}

LA4329

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=26&page=show_problem&problem=2330

题意:

一条大街上住着n个乒乓球爱好者,经常组织比赛。每个人都有一个技能值ai,每场比赛需要3个人:两名选手和一名裁判。规定裁判位置必须在两个选手的中间,而且技能值也必须在两个选手的中间,问一共能组织多少种比赛。

分析:

和上题类似,每个技能值有的话为 1 ,否则为 0 ,每一个点都可以做裁判,那么他能组织多少场比赛?

a1~ai-1 有 ci个比 ai 小,ai+1~an有di个比他小,乘法加法原理,ci(n-i-di) + di(i-ci-1)。

 #include <bits/stdc++.h>

 using namespace std;

 inline int lowbit(int x) {
return x&-x;
} struct FenwickTree {
int n;
vector<int> C; void resize(int n) {
this->n = n;
C.resize(n);
} void clear() {
fill(C.begin(),C.end(),);
} //计算A[1] + A[2] + ... +A[n]
int sum(int x) {
int ret = ;
while(x>) {
ret +=C[x];
x -=lowbit(x);
}
return ret;
} // A[x] +=d;
void add(int x,int d) {
while(x<=n) {
C[x] +=d;
x +=lowbit(x);
}
}
}; const int maxn = + ;
int n;
int a[maxn];
FenwickTree f;
int c[maxn],d[maxn]; int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int maxa = ;
scanf("%d",&n);
for(int i=;i<=n;i++) {
scanf("%d",&a[i]);
maxa = max(maxa,a[i]);
} f.resize(maxa);
f.clear(); for(int i=;i<=n;i++) {
f.add(a[i],);
c[i] = f.sum(a[i]-);
} f.clear();
for(int i=n;i>=;i--) {
f.add(a[i],);
d[i] = f.sum(a[i]-);
} long long ans = ;
for(int i=;i<=n;i++) {
ans +=(long long)c[i]*(n-i-d[i]) + (long long)(i-c[i]-)*d[i];
}
printf("%lld\n",ans);
} return ;
}
												

二叉索引树,LA2191,LA5902,LA4329的更多相关文章

  1. 【转载】区间信息的维护与查询(一)——二叉索引树(Fenwick树、树状数组)

    在网上找到一篇非常不错的树状数组的博客,拿来转载,原文地址. 树状数组 最新看了一下区间的查询与修改的知识,最主要看到的是树状数组(BIT),以前感觉好高大上的东西,其实也不过就这么简单而已. 我们有 ...

  2. 二叉索引树BIT

    定义     二叉索引树,binary index tree,又名树状数组,或Fenwick Tree,因为本算法由Fenwick创造.     对于数组A,定义Query(i,j) = Ai +Ai ...

  3. C++实用数据结构:二叉索引树

    看下面这个问题(动态连续和查询): 有一个数组A(长度为n),要求进行两种操作: add(i,x):让Ai增大x: query(a,b):询问Aa+Aa+1+...+Ab的和: 若进行模拟,则每次qu ...

  4. POJ 3321 Apple Tree dfs+二叉索引树

    题目:http://poj.org/problem?id=3321 动态更新某个元素,并且求和,显然是二叉索引树,但是节点的标号不连续,二叉索引树必须是连续的,所以需要转化成连续的,多叉树的形状已经建 ...

  5. NYOJ 116 士兵杀敌(二)(二叉索引树)

    http://acm.nyist.net/JudgeOnline/problem.php?pid=116 题意: 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的 ...

  6. HDU 1166 敌兵布阵(线段树 or 二叉索引树)

    http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意:第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N<=50000),表示敌人有 ...

  7. 【树状数组(二叉索引树)】轻院热身—candy、NYOJ-116士兵杀敌(二)

    [概念] 转载连接:树状数组 讲的挺好. 这两题非常的相似,查询区间的累加和.更新结点.Add(x,d) 与 Query(L,R) 的操作 [题目链接:candy] 唉,也是现在才发现这题用了这个知识 ...

  8. 树状数组(二叉索引树 BIT Fenwick树) *【一维基础模板】(查询区间和+修改更新)

    刘汝佳:<训练指南>Page(194) #include <stdio.h> #include <string.h> #include <stdlib.h&g ...

  9. 1.红黑树和自平衡二叉(查找)树区别 2.红黑树与B树的区别

    1.红黑树和自平衡二叉(查找)树区别 1.红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单. 2.平衡 ...

随机推荐

  1. bios-----> grub

    系统有两块硬盘, 第一块安装的win7, 第二块安装ubuntu 默认从sda加载grub 如果在bios页面选择从sdb启动,会找不到grub 进入原来的sda系统,  grub-install / ...

  2. java——删除链表中等于给定值的所有元素

    class ListNode{ int val ; ListNode next; public ListNode(int x) { val = x; } public ListNode(int[] a ...

  3. Webstrom 中写Vue没有代码提示如何解决?

    1. 如果你的Webstorm是2017版的,请更新到最新的2018,2018版本的webstorm自带了vue插件 找到 Help > About,查看你的Webstorm版本 2. 如果你的 ...

  4. Hive学习(一)

    https://www.cnblogs.com/qingyunzong/p/8707885.html http://www.360doc.com/content/16/1006/23/15257968 ...

  5. 多线程编程_控制并发线程数的Semaphore

    简介 Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源.很多年以来,我都觉得从字面上很难理解Semaphore所表达的含义,只能把它比作是 ...

  6. 如何成为一名:黑客/Programmer/Python高手

    如何成为一名黑客 Eric Steven Raymond https://translations.readthedocs.org/en/latest/hacker_howto.html How To ...

  7. maya安装不了

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...

  8. 浅入分析Linux

    Linux 操作系统必须完成的两个主要目的 与硬件部分交互, 为包含在硬件平台上的所有底层可编程部件提供服务 为运行在计算机系统上的应用程序(即所谓的用户空间)提供执行环境 一些操作系统运行所有的用户 ...

  9. Cgroup blkio简介和测试(使用fio测试)

    Cgroup blkio简介和测试(使用fio测试) 因需要对docker镜像内的进程对磁盘读写的速度进行限制,研究了下Cgroup blkio,并使用fio对其iops/bps限速进行测试. Cgr ...

  10. react做股票、期货交易遇到的问题(不完全是react)及解决方法。

    公司项目主要是做股票及期货行情展示及交易,h5相应的做了一些功能---可以看行情图及模拟交易,实盘交易存在一定的风险,老板希望做自己的产品,这样h5就尴尬了,不过没关系,项目里还是有一定技术含量的-- ...