ACM暑假训练 问题 G: Balanced Photo (树状数组优化)
2017-07-26 18:36
411 查看
问题 G: Balanced Photo
时间限制: 1 Sec 内存限制: 128 MB提交: 67 解决: 17
[提交][状态][讨论版]
题目描述
Farmer John is arranging his N cowsin a line to take a photo (1≤N≤100,000).
The height of the ith
cow in sequence ishi,
and the heights of all cows are distinct.
As with all photographs of his cows, FJ wants this one to come out looking as nice as possible. He decides that cow i looks
"unbalanced" if Li and Ri differ
by more than factor of 2, where Li and Ri are
the number of cows taller than i on
her left and right, respectively. That is, i is
unbalanced if the larger of Li and Ri is
strictly more than twice the smaller of these two numbers. FJ is hoping that not too many of his cows are unbalanced.
Please help FJ
eef2
compute the total number of unbalanced cows.
输入
Thefirst line of input contains N.
The next N lines
contain h1…hN,
each a nonnegative integer at most 1,000,000,000.
输出
Pleaseoutput a count of the number of cows that are unbalanced.
样例输入
7 34 6 23 0 5 99 2
样例输出
3
提示
In this example,the cows of heights 34, 5, and 2 are unbalanced.
【解析】:
十万的数据量,两层循环必定超时。
先给这个数列排排名次,不妨让最小的当第一名,最高的当最后一名,
这样得到一个排名的数列,而且不会改变原数列的前后之间的大小关系。不妨令此数列为数组d
有了数列 d,我们从左往右扫一遍数列 d。另外申请一个数组 c 做辅助。
c[ i ] 表示i左边比 d[ i ] 小的数目。
扫到d[ i ] 的时候用temp=c[ i ] 得到当前i的前面有多少个比d[ i ] 小的数。再用i-temp+1即得到了左边的大数的数目。
然后让所有的小于d[i]的 j ,使得c[ j ]加1。表示比d[i]小的数目全都加1
与此同时,记录下i左边的大的数,存入L[ i ];
代码说一下就是:
for(int i=1;i<=n;i++) { int temp=c[i];//i左边的矮牛数 L[i]=i-temp-1;//i左边的高牛数 for(int j=1;j<=d[i];j++) c[j]++; }
但是这样必定超时,所以数组c用树状数组来维护,就可以避免内层for循环。复杂度从O(n^2)降到O(n*log(n));
如上,左边的高牛数完了,把数列倒过来再数一遍得到R[ i ]。
【代码】:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int n,c[520000],a[520000]; int t[520000],d[520000]; int L[520000],R[520000]; bool cmp(int x,int y){ return a[x]<a[y]; } void add(int k,int num) { while(k<=n){ c[k]+=num; k+=k&-k; } } int find(int k) { int sum=0; while(k){ sum+=c[k]; k-=k&-k; } return sum; } int main() { cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; t[i]=i; } sort(t+1,t+1+n,cmp); for(int i=1;i<=n;i++) { d[t[i]]=i;//身高序号 } //数组d把原序列按大小分配序号,但原序列不变 for(int i=1;i<=n;i++)//从左数牛 { int temp=find(d[i]);//i左边的矮牛数 L[i]=i-temp-1;//i左边的高牛数 add(d[i],1); } memset(c,0,sizeof(c));//树状数组清0 for(int i=n;i>=1;i--)//从右边数得到右边,原理同左 { int temp=find(d[i]);//i右边的矮数目 R[i]=n-i-temp; //i右边的高牛数目 add(d[i],1); } int ans=0; for(int i=1;i<=n;i++) { if(2*min(L[i],R[i])<max(L[i],R[i])) ans++; } cout<<ans<<endl; return 0; }
相关文章推荐
- 17暑期ACM俱乐部个人训练赛第2场 G Balanced Photo (树状数组)
- 2017暑假训练之树状数组
- HDU - 1556 Color the ball解题报告(树状数组 处理区间问题)
- 暑假编程训练---E:年龄问题
- 训练深度模型的优化问题(二)
- 训练深度模型的优化问题(十)
- 北京师范大学第十四届ACM决赛- B Squared Permutation 树状数组
- 山东理工ACM【1135】C/C++经典程序训练5---图形打印问题
- HDU 5517 (ACM 2015 沈阳) Triple [树状数组]
- HDU 2642 二维树状数组问题
- 【扩展KMP】【树状数组优化dp】字符串游戏
- [ACM] hdu 1166 敌兵布阵(树状数组)
- [BZOJ3594] [Scoi2014]方伯伯的玉米田 二维树状数组优化dp
- 用树状数组解决区间查询问题
- Codeforces 629D Babaei and Birthday Cake(树状数组优化dp)
- 暑假-树状数组-C - Ping pong
- [ACM] hrbustoj 1161 Leyni (树状数组)
- C语言 杭电ACM 1276 士兵队列训练问题
- 【HDU5892 2016 ACM ICPC Asia Regional Shenyang Online A】【二维树状数组模板 区间修改】nn矩阵内子矩阵中各怪兽数量的奇偶性.cpp
- POJ 1804 逆序对问题【分治】【线段树】【树状数组】【平衡树】