二叉索引树,LA2191,LA5902,LA4329
利用了二进制,二分的思想的一个很巧妙的数据结构,一个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
题意:
一条大街上住着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的更多相关文章
- 【转载】区间信息的维护与查询(一)——二叉索引树(Fenwick树、树状数组)
在网上找到一篇非常不错的树状数组的博客,拿来转载,原文地址. 树状数组 最新看了一下区间的查询与修改的知识,最主要看到的是树状数组(BIT),以前感觉好高大上的东西,其实也不过就这么简单而已. 我们有 ...
- 二叉索引树BIT
定义 二叉索引树,binary index tree,又名树状数组,或Fenwick Tree,因为本算法由Fenwick创造. 对于数组A,定义Query(i,j) = Ai +Ai ...
- C++实用数据结构:二叉索引树
看下面这个问题(动态连续和查询): 有一个数组A(长度为n),要求进行两种操作: add(i,x):让Ai增大x: query(a,b):询问Aa+Aa+1+...+Ab的和: 若进行模拟,则每次qu ...
- POJ 3321 Apple Tree dfs+二叉索引树
题目:http://poj.org/problem?id=3321 动态更新某个元素,并且求和,显然是二叉索引树,但是节点的标号不连续,二叉索引树必须是连续的,所以需要转化成连续的,多叉树的形状已经建 ...
- NYOJ 116 士兵杀敌(二)(二叉索引树)
http://acm.nyist.net/JudgeOnline/problem.php?pid=116 题意: 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的 ...
- HDU 1166 敌兵布阵(线段树 or 二叉索引树)
http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意:第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N<=50000),表示敌人有 ...
- 【树状数组(二叉索引树)】轻院热身—candy、NYOJ-116士兵杀敌(二)
[概念] 转载连接:树状数组 讲的挺好. 这两题非常的相似,查询区间的累加和.更新结点.Add(x,d) 与 Query(L,R) 的操作 [题目链接:candy] 唉,也是现在才发现这题用了这个知识 ...
- 树状数组(二叉索引树 BIT Fenwick树) *【一维基础模板】(查询区间和+修改更新)
刘汝佳:<训练指南>Page(194) #include <stdio.h> #include <string.h> #include <stdlib.h&g ...
- 1.红黑树和自平衡二叉(查找)树区别 2.红黑树与B树的区别
1.红黑树和自平衡二叉(查找)树区别 1.红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单. 2.平衡 ...
随机推荐
- my16_sql_thread执行慢导致主从延迟高的一个情景
现象:从库延迟高,查看slave status发现sql_thread执行语句的速度比主库慢,这样的延迟会一直高下去,下面是排查的一些过程1. 检查了从库的配置,磁盘的写入速度的确没有主库高2. io ...
- var在IE中的问题
一个朋友问了一个js问题, 一段看不出有任何问题的代码, 在ie下报错:”object doesn’t support this property or method”. function foo(o ...
- 转 python 的常用函数replace, split(),enumerate() 函数
1.execmd = "su - " + ou + " -c 'sqlplus / as sysdba << EOF\n " + execmd3 + ...
- JavaSE---多线程---线程的生命周期
1.线程的生命周期:新建.就绪.运行.阻塞.死亡 2.运行状态线程进入阻塞: 1.1 调用sleep方法主动放弃: 1.2 调用线程的suspend方法将线程挂起,不推荐使用: 1.3 线程调用一个阻 ...
- android Firebase中配置 Crashlytics
首先登陆Google账号 https://firebase.google.com/ 创建项目 配置Android 1.注册应用 2.下载配置文件 3.添加firebaseSDk 配置后台分析的Cras ...
- cpp 学习笔记
1.C++中模仿gets是 getline(cin, string object) #include <bits/stdc++.h> #define IOS ios::sync_with ...
- 实例化php类的时候如何传参
当我们实例化一个php类的时候,要怎么传递参数呢?这取决于该类的构造方法. 例: person.class.php <?php class person{ var $name; var $col ...
- POJ 3522 ——Slim Span——————【最小生成树、最大边与最小边最小】
Slim Span Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7102 Accepted: 3761 Descrip ...
- CentOS7 安装oracle 客户端
参考 http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html 下载 oracle-instantclient11. ...
- intellijidea课程 intellijidea神器使用技巧1-5 idea界面介绍
菜单栏介绍: file:文件操作edit:文本操作view:视图操作navigate:跳转code:源码文件analyze:项目依赖关系分析refactor:代码重构快捷操作,如:抽取函数build: ...