树状数组-HDU3015 Disharmony Trees
目录
- 树状数组
- 例题
- 题意
- 分析
- 代码
- 小结
- 相关推荐
树状数组
- 什么是树状数组? 简单来说,就是暴力遍历数组来解决区间问题等,不过遍历的路径使用了位运算来进行压缩,复杂度是O(log2(n))这样就不会超时了(为所欲为?)。
- lowbit()操作 其核心是神奇的lowbit操作,lowbit(x)=x&(-x),它的功能是找到x的二进制数的最后一个1,原理是利用负数的补码表示,补码是原码取反加一。例如x=6=00000110(2),-x=x补=11111010(2),那么lowbit(x)=x&(-x)=10(2)=2。 从lowbit()引出数组a[],a[x]的值是把ax(题目输入初始值)和他前面的m个数相加,如下表所示:
图形化:
那么通过数组a[],就可以求sum,例如sum(8)=a[8],sum(7)=a[7]+a[6]+a[4],sum(6)=a[6]+a[4],如此一来不就是我们要的路径压缩了吗? 同样地,更新ax时也要更新a[],例如更新a3,那么首先更改a[3];然后3+lowbit(3)=4,更改a[4];接着4+lowbit(4)=8,更改a[8]。
例题
传送门: HDU-3015
One day Sophia finds a very big square. There are n trees in the square. They are all so tall. Sophia is very interesting in them.
She finds that trees maybe disharmony and the Disharmony Value between two trees is associated with two value called FAR and SHORT. The FAR is defined as the following:If we rank all these trees according to their X Coordinates in ascending order.The tree with smallest X Coordinate is ranked 1th.The trees with the same X Coordinates are ranked the same. For example,if there are 5 tree with X Coordinates 3,3,1,3,4. Then their ranks may be 2,2,1,2,5. The FAR of two trees with X Coordinate ranks D1 and D2 is defined as F = abs(D1-D2). The SHORT is defined similar to the FAR. If we rank all these trees according to their heights in ascending order,the tree with shortest height is ranked 1th.The trees with the same heights are ranked the same. For example, if there are 5 tree with heights 4,1,9,7,4. Then their ranks may be 2,1,5,4,2. The SHORT of two trees with height ranks H1 and H2 is defined as S=min(H1,H2). Two tree’s Disharmony Value is defined as F*S. So from the definition above we can see that, if two trees’s FAR is larger , the Disharmony Value is bigger. And the Disharmony value is also associated with the shorter one of the two trees. Now give you every tree’s X Coordinate and their height , Please tell Sophia the sum of every two trees’s Disharmony value among all trees.
input:
There are several test cases in the input For each test case, the first line contain one integer N (2 <= N <= 100,000) N represents the number of trees. Then following N lines, each line contain two integers : X, H (0 < X,H <=1,000,000,000 ), indicating the tree is located in Coordinates X and its height is H.
output:
For each test case output the sum of every two trees’s Disharmony value among all trees. The answer is within signed 64-bit integer.
Sample Input:
2
10 100
20 200
4
10 100
50 500
20 200
20 100
Sample Output:
1
13
题意
给出N棵树的坐标X和高度H,定义两棵树的不和谐值为FAR*SHORT,其中FAR=abs(x1-x2),SHORT=min(h1,h2),注意此时的x,h是排序后的排名,且有同名情况。求总的不和谐值。
分析
- 数据处理: 读入pair<坐标X,原始下标>x[],排序后处理同名情况,高度H同理,最后拼接得到pair<相对坐标,相对高度>p[]。
- 维护两个树状数组: 因为SHORT=min(h1,h2),那我们对p[]按高度降序排序,然后遍历p[],每次即得到了当前的最小高度SHORT,然后乘上之前所有树的FAR即可。 那么FAR怎么求呢??? 此时维护数组cnt[]表示数量,dis[]表示坐标,总FAR=FAR左+FAR右(因为是按高度排序,不是坐标,所以有左右之分),FAR左=左边树的数量×当前树坐标-左边树的坐标和,就得到了左边所有树到当前树的距离; 同样的,FAR右=右边树的坐标和-右边树的数量×当前树的坐标。 至此维护数组更新答案就好了。
代码
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn = 100005;
pair<ll, ll>p[maxn], x[maxn], h[maxn];
int n;
ll cnt[maxn], dis[maxn];
bool cmp(pair<ll, ll>a, pair<ll, ll>b) {
return a.second > b.second;
}
int lowbit(int x) {
return x & (-x);
}
ll sum(ll* bit, int x) {
ll res = 0;
for (int i = x; i > 0; i -= lowbit(i))
res += bit[i];
return res;
}
ll sum(ll* bit, int from, int to) {
return sum(bit, to - 1) - sum(bit, from - 1);
}
void update(ll* bit, int x, ll y) {
for (int i = x; i <= maxn; i += lowbit(i))
bit[i] += y;
}
int main() {
while (~scanf("%d", &n)) {
//1.数据处理
for (int i = 1; i <= n; i++) {
scanf("%lld%lld", &x[i].first, &h[i].first);
x[i].second = h[i].second = i;
}
sort(x + 1, x + n + 1);
sort(h + 1, h + n + 1);
ll tx = x[1].first, th = h[1].first, ans = 0;
x[1].first = h[1].first = 1;
for (int i = 2; i <= n; i++) {//同名处理
if (x[i].first == tx)
x[i].first = x[i - 1].first;
else {
tx = x[i].first;
x[i].first = i;
}
if (h[i].first == th)
h[i].first = h[i - 1].first;
else {
th = h[i].first;
h[i].first = i;
}
}
for (int i = 1; i <= n; i++) {
p[x[i].second].first = x[i].first;
p[h[i].second].second = h[i].first;
}
//2.维护两个树状数组
sort(p + 1, p + 1 + n, cmp);//高度降序
memset(cnt, 0, sizeof(cnt));
memset(dis, 0, sizeof(dis));
for (int i = 1; i <= n; i++) {
ll cx = p[i].first, ch = p[i].second;//当前树坐标和高度
ll left = sum(cnt, 1, cx), right = sum(cnt, cx + 1, maxn);//左边树的数量和右边树的数量
ans += ch * (left * cx - sum(dis, 1, cx) + sum(dis, cx + 1, maxn) - right * cx);
update(cnt, cx, 1);//更新数量
update(dis, cx, cx);//更新坐标
}
printf("%lldn", ans);
}
return 0;
}
小结
看见求和,坐标等关键词时,普通模拟会超时则可以考虑转换成树状数组题型来求解,重点是如何转换,若要用到多个树状数组时,一般会有最值比较排序。
相关推荐
题目推荐:
博文推荐
原创不易,请勿转载(
本不富裕的访问量雪上加霜) 博主首页:https://blog.csdn.net/qq_45034708
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MySQL如何管理客户端连接?线程池篇
- 让python装饰器不再晦涩难懂
- Android开发3年,九月份面试12家大厂跳槽成功,我有一些面试经验想分享给你们
- MySQL的防火墙功能
- Java中线程池的参数有几个?
- MySQL企业版备份工具MEB
- python生成器函数的应用场景举例---为copy过程添加进度条显示
- 短网址程序YOURLS安装及配置教程与设置中文
- MGR用哪个版本?5.7 vs 8.0
- 同事直呼666!小姐姐仅用3行代码就能玩出花来
- MySQL升级至8.0需要考虑哪些因素?
- 某云Music——JS破解全过程
- 和低效 IO 说再见,回头补一波 Java 7 的 NIO.2 特性
- 框架源码调试实战之easypoi异常解决方案精讲
- MySQL8.0的错误日志