二叉索引树,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.平衡 ...
随机推荐
- sqlserver 事务日志
预写式日志(Write-Ahead Logging (WAL)) --在数据写入到数据库之前,先写入到日志. 1.”Begin Tran”记录 -> 缓冲区 2. 日志 ...
- 小程序自定义modal弹窗封装实现
前言小程序官方提供了 wx.showModal 方法,但样式比较固定,不能满足多元化需求,自定义势在必行~ 老规矩先上图 点击某个按钮,弹出 modal框,里面的内容可以自定义,可以是简单的文字提示, ...
- 7.JSP简介
---恢复内容开始--- 1.JSP简介 Java动态网页技术标准(Java Server Pages)是基于Servlet技术以及整个Java体系的Web开发技术是用于动态生成HTML文档的Web页 ...
- kafka删除主题数据和删除主题
1.删除主题 在server.properties中增加设置,默认未开启 delete.topic.enable=true 删除主题命令 /bin/kafka-topics --delete --to ...
- Python入妖5-----正则的基本使用
什么是正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是 事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符”,这个“规则字符” 来表达对字符的一种过滤逻辑. 正则并不是pyth ...
- Maven 错误 Failure to transfer ...was cached in the local repository...
Maven 错误 Failure to transfer ...was cached in the local repository... 我解决的时候多了两步才解决 1. mvn clean ins ...
- httpUrlConnection连接网络的用法(用到了handle传递消息,在主线程中更新UI)
由于httpclient在Android5.0以后已经过时,所以官方推荐使用httpUrlConnection来连接网络,现将该连接的基本方法展示,如下 注意:记得加入<uses-permiss ...
- ErlangC 最佳人力效益指标
以平均服务时间(AHT)180秒,顾客来电量每15分钟150通以及服务目标时间在20秒内为例子说明最佳人力效益指标.此假设条件下由Erlang C模拟器的结果如下图, 假设我希望客服中心的期望服务水准 ...
- Quartz使用(4) - Quartz监听器Listerner
1. 概述 Quartz的监听器用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知.类似于任务执行过程中的邮件.短信类的提醒.Quartz监听器主要有JobListener.Trigger ...
- This blog Test the Open Live Writer
1. We print HELLOWORLD when we first learned to code, I want to Write this blog to test the software ...