LA 4329 Ping pong 树状数组
对于我这样一名脑残ACMer选手,这道题看了好久好久大概4天,终于知道怎样把它和“树状数组”联系到一块了。
树状数组是什么意思呢?用十个字归纳它:心里有数组,手中有前缀。
为什么要用树状数组?假设你要储存一段数字的前缀和,还要动态修改这些数字。怎么办?
通常的想法就是用数组a[]保存所有的数字,再用数组s[]保存每一位上的前缀和。
for(int i=;i<=n;i++){ s[i]=s[i-]+a[i]; }
这样有一个弊端,就是当你动态修改a[]数组中的数字的时候,维护s[]数组的代价太高了,最坏可达O(N),每修改一次都要O(N)的代价对于n=1000,000这样的的数据,显然修改十几次就要超时了。
那么这时候就可以用树状数组来存了,它的复杂度只有O(logN)。
也就是相当于把n二分的速度,非常快。
首先假设一个数组A[]和另一个保存其子串前缀和的数组C[],形状如下图:
对于A[]数组,就是我所介绍的,心中的数组。
而C[]数组,就是手中的子串前缀和。
引入一个lowbit(x)的概念,lowbit(x)定义为x的二进制位最右边的1所对应的值,比如1表示1,10表示2,100表示4,这就是他们的值。lowbit只会为2^k(k>=0)。
令C[x]=A[x-lowbit(x)+1]+A[x-lowbit(x)+2]+...+A[x],那么每个C[x]都会对应一部分它的lowbit(x)范围内的A[i]。
假如我要求x的前缀和,只要先取出C[x],再取出C[x-lowbit(x)]也就是C[x]的左边界,令x=lowbit(x)也就是原来的C[x]的左边界的再左边一位,依次重复取C[x],直到x=0。
比如拿x=7做一个示范,我要求x=7的前缀和,也就是A[1]+A[2]+...+A[7],如下图:
这样就求得了A[7]的前缀和。
实现:
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int ret=;
for(;x;x-=lowbit(x))
ret+=C[x];
return ret;
}
那当A[]某一位数据发生了变化,应该维护C[]的值,要注意A[]其实是你心里的数组,而C[]才是它的表现形式。
维护C[]就像是求有哪些C[]覆盖到了A[i],对于A[3]来打个比方,如下图所示:
每次向右上方“爬”,x=3开始,修改C[x],x加上自己的lowbit(x),此时x=4,再修改C[4],x加上自己的lowbit(x),此时x=8,直到x超出了C数组的上界。
实现:
void updata(int x,int d)
{
for(;x<=maxn;x+=lowbit(x))
C[x]+=d;
}
现在把树形数组的概念运用到这道题里面来实践一下。
把运动员排成一排,对于其中任意一个位置i上的人来说,如果他作为裁判,则有这么两种可能:
1.左边的某人能力值低于他,右边高于他;
2.左边的某人能力值高于他,右边低于他。
记左边比他小的人数为l[i],右边比他小的人数为r[i],
那么左边比他大的人数为i-1-l[i],右边比他大的人数为n-i-r[i],
则i作为裁判就有l[i]*(n-i-r[i])+(i-1-l[i])*r[i];
求l[i]的方法呢,就是创一个hash数组,从a[1]扫到a[i-1],对hash[a[k]]++,判断hash[]中a[i]的前缀和,也就是l[i]的值了;
前缀和就是用树状数组保存和维护。
r[i]类似,只不过是逆序读取a[i]构造hash表。
实现:
#include <stdio.h>
#include <string.h>
const int maxn=;
int C[maxn];
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int ret=;
for(;x;x-=lowbit(x))
ret+=C[x];
return ret;
}
void updata(int x)
{
for(;x<=maxn;x+=lowbit(x))
C[x]++;
}
int a[maxn],cc[maxn],dd[maxn];
int main()
{
int i,t,n;
long long ans;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=;i<=n;i++) scanf("%d",&a[i]);
memset(C,,sizeof(C));
for(i=;i<=n;i++){
cc[i]=sum(a[i]);
updata(a[i]);
}
memset(C,,sizeof(C));
for(i=n;i;i--){
dd[i]=sum(a[i]);
updata(a[i]);
}
ans=;
for(i=;i<=n;i++)
ans+=1LL*cc[i]*(n-i-dd[i])+1LL*(i--cc[i])*dd[i];
printf("%lld\n",ans);
}
return ;
}
LA 4329 Ping pong 树状数组的更多相关文章
- LA 4329 - Ping pong 树状数组(Fenwick树)
先放看题传送门 哭瞎了,交上去一直 Runtime error .以为那里错了. 狂改!!!!! 然后还是一直... 继续狂改!!!!... 一直.... 最后发现数组开小了.......... 果断 ...
- UVALive - 4329 Ping pong 树状数组
这题不是一眼题,值得做. 思路: 假设第个选手作为裁判,定义表示在裁判左边的中的能力值小于他的人数,表示裁判右边的中的能力值小于他的人数,那么可以组织场比赛. 那么现在考虑如何求得和数组.根据的定义知 ...
- Ping pong(树状数组经典)
Ping pong Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- poj3928 Ping pong 树状数组
http://poj.org/problem?id=3928 Ping pong Time Limit: 1000MS Memory Limit: 65536K Total Submissions ...
- UVA 1428 - Ping pong(树状数组)
UVA 1428 - Ping pong 题目链接 题意:给定一些人,从左到右,每一个人有一个技能值,如今要举办比赛,必须满足位置从左往右3个人.而且技能值从小到大或从大到小,问有几种举办形式 思路: ...
- LA4329 Ping pong 树状数组
题意:一条大街上住着n个乒乓球爱好者,经常组织比赛切磋技术.每个人都有一个能力值a[i].每场比赛需要三个人:两名选手,一名裁判.他们有个奇怪的约定,裁判必须住在两名选手之间,而裁判的能力值也必须在两 ...
- POJ 3928 Ping pong 树状数组模板题
開始用瓜神说的方法撸了一发线段树.早上没事闲的看了一下树状数组的方法,于是又写了一发树状数组 树状数组: #include <cstdio> #include <cstring> ...
- HDU 2492 Ping pong (树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Ping pong Problem Description N(3<=N<=2000 ...
- hdu 6203 ping ping ping(LCA+树状数组)
hdu 6203 ping ping ping(LCA+树状数组) 题意:给一棵树,有m条路径,问至少删除多少个点使得这些路径都不连通 \(1 <= n <= 1e4\) \(1 < ...
随机推荐
- Jvascript简介
一.Javascript就是我们所说的脚本语言.它不同于C++/java等语言,它更加灵活! 正因为其灵活性,没有那么多的规章制度,也是我们容易学的地方,但很多时候也是 令人无奈的地方! 二.我们要知 ...
- windows2013 iis 配置 xcache
本帖最后由 artsharp 于 2010-6-8 09:06 编辑XCache是一种新的php缓存器,经过测试,在Windows下效果比同类软件强很多.实际测试效果如下(非科学方法):原网页平均执行 ...
- spring的显示装配bean(1)------通过XML文件装配
1:spring环境的简单搭建 (1)导入spring相关的jar包. 2:准备要进行装配的Java类 这里给出两个举例类 (1) (2) 3:配置XML文件 (1)在配置文件的顶部声明多个XML模式 ...
- linux vps安装kloxo配置全部过程
第一步如何登录Linux VPS进行远程(SSH)管理 很多人可能用过免费虚拟主机,但绝没有用过好用的免费服务器租用,仅有的少数免费服务器都只针对有较高访问量的大站(以交换广告为条件),而普通小站是无 ...
- 2017技术核心——Spring
从毕业从事Java WEB开始到现在已差不多快5年时间了,一直使用的Spring相关的技术,其实最主要的是SpringMVC这一块.其实,一直停留在用的地步,并不知晓其原理,真正耐下心来去研究Spri ...
- canvas绘制二次贝塞尔曲线----演示二次贝塞尔四个参数的作用
canvas中绘制二次贝塞尔曲线的方法为ctx.quadraticCurveTo(x1,y1,x2,y2); 四个参数分别为两个控制点的坐标.开始点即当前canvas中目前的点,如果想从指定的点开始, ...
- AOP学习心得&jdk动态代理与cglib比较
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- C# 依赖注入
http://www.cnblogs.com/leoo2sk/archive/2009/06/17/1504693.html 这篇文章真的非常非常好···绝对值得收藏学习. 目录 目录 1 ...
- java并发编程-基础
线程带来的风险 安全性:多线程操作执行顺序的不可预测性 -- 永远不发生糟糕的事情: 活跃性:代码无法得到执行,死锁.饥饿问题 -- 某件正确的事情最终会发生: 性能问题:活跃性只意味着某件事最终会发 ...
- 贪吃蛇的java代码分析(一)
自我审视 最近自己学习java已经有了一个多月的时间,从一开始对变量常量的概念一无所知,到现在能勉强写几个小程序玩玩,已经有了长足的进步.今天没有去学习,学校里要进行毕业答辩和拍毕业照了,于是请了几天 ...