对于我这样一名脑残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 树状数组的更多相关文章

  1. LA 4329 - Ping pong 树状数组(Fenwick树)

    先放看题传送门 哭瞎了,交上去一直 Runtime error .以为那里错了. 狂改!!!!! 然后还是一直... 继续狂改!!!!... 一直.... 最后发现数组开小了.......... 果断 ...

  2. UVALive - 4329 Ping pong 树状数组

    这题不是一眼题,值得做. 思路: 假设第个选手作为裁判,定义表示在裁判左边的中的能力值小于他的人数,表示裁判右边的中的能力值小于他的人数,那么可以组织场比赛. 那么现在考虑如何求得和数组.根据的定义知 ...

  3. Ping pong(树状数组经典)

    Ping pong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  4. poj3928 Ping pong 树状数组

    http://poj.org/problem?id=3928 Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions ...

  5. UVA 1428 - Ping pong(树状数组)

    UVA 1428 - Ping pong 题目链接 题意:给定一些人,从左到右,每一个人有一个技能值,如今要举办比赛,必须满足位置从左往右3个人.而且技能值从小到大或从大到小,问有几种举办形式 思路: ...

  6. LA4329 Ping pong 树状数组

    题意:一条大街上住着n个乒乓球爱好者,经常组织比赛切磋技术.每个人都有一个能力值a[i].每场比赛需要三个人:两名选手,一名裁判.他们有个奇怪的约定,裁判必须住在两名选手之间,而裁判的能力值也必须在两 ...

  7. POJ 3928 Ping pong 树状数组模板题

    開始用瓜神说的方法撸了一发线段树.早上没事闲的看了一下树状数组的方法,于是又写了一发树状数组 树状数组: #include <cstdio> #include <cstring> ...

  8. HDU 2492 Ping pong (树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Ping pong Problem Description N(3<=N<=2000 ...

  9. hdu 6203 ping ping ping(LCA+树状数组)

    hdu 6203 ping ping ping(LCA+树状数组) 题意:给一棵树,有m条路径,问至少删除多少个点使得这些路径都不连通 \(1 <= n <= 1e4\) \(1 < ...

随机推荐

  1. idea intellij 混淆anroid代码

    idea intellij 混淆anroid代码 在project.properties中加入 target=android-14proguard.config=proguard.cfg 点击 Bui ...

  2. [canvas]用canvas绘制饼状图

    折线图之后又来饼状图啦~\(≧▽≦)/~啦啦啦 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  3. NOIP2014初赛分数线及金华上线名单

    NOIP2014初赛分数线及金华上线名单 分数线:提高组81.5,普及组93 这分数线还能再高些吗?悲催的浙江. 金华上线普及组名单: 地市 姓名 学校 年级 参赛语种 成绩 金华 成浩鹏 稠州丹溪校 ...

  4. 从零开始编写自己的C#框架(3)——开发规范(转)

    由于是业余时间编写,而且为了保证质量,对写出来的东西也会反复斟酌,所以每周只能更新两章左右,请大家谅解,也请大家耐心等待,谢谢大家的支持. 初学者应该怎样学习本系列内容呢?根据我自己的学习经验,一般直 ...

  5. jQuery文本段落展开和折叠效果

    <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/h ...

  6. selenium定位页面元素的一件趣事

    PS:本博客selenium分类不会记载selenium打开浏览器,定位元素,操作页面元素,切换到iframe,处理alter.confirm和prompt对话框这些在网上随处可见的信息:本博客此分类 ...

  7. EditText添加了ImageSpan后,在两者中间不能输入纯文本

    严格来说是连续插入两个ImageSpan之后,在其中间不能够输入纯文本内容. 最后发现问题出现在了SpannableString在设置ImageSpan的时候第四个参数flag的问题. spannab ...

  8. mysql 联合查询后update

    SELECT a.user_name,a.avatar,a.nicheng,a.user_rank,b.rank_name,b.rank_img FROM ecs_users a , ecs_user ...

  9. node-webkit 桌面开发 初入1

    node-webkit  是什么就不介绍了 注意官网的一句话 ”node-webkit is based on Chromium and node.js " 所以node-webkit 实际 ...

  10. sql server 删除表及表的相关视图、存储过程、方法

    注意:进行此操作前需先备份数据库,免得删错无法恢复 1.查询 SELECT Name ,type FROM SysObjects WHERE name LIKE '%cases%' 2.拼接语句 SE ...