hdu 5147 Sequence II(前缀和,后缀和)
来源:互联网 发布:冰川网络收购棋牌游戏 编辑:程序博客网 时间:2024/06/05 02:16
Please calculate how many quad (a,b,c,d) satisfy:
1.
2.
3.
Each test case begins with a line contains an integer n.
The next line follows n integers
[Technical Specification]
1 <= T <= 100
1 <= n <= 50000
1 <=
151 3 2 4 5
4题意: 给定1~n的一个排列 用A[ ]数组保存,问有多少下标四元组(a,b,c,d)满足:a<b<c<d 且 A[a] < A[b] , A[c] < A[d].
思路为: 枚举c的位置,那么每一次枚举中的方法数为 1到c-1中 (a,b)的个数 乘以 c到n中(c,d)的个数. 累加起来即为答案。
1-c-1中(a,b)的个数相当于枚举b的位置,然后计算出b前面有多少数比A[b]小,该值要保存下来,下一次枚举c的时候,该值再加上c-1前面有多少比a[c-1]小的数即为当前情况下1-c-1中(a,b)的个数,也就是b=c-1的时候,因为枚举b之前的情况已经算过了。
举个例子:
当c枚举到第3时,b已经枚举完了1,2,并把当前(a,b)的方法数保存,等c枚举到4时,刚才保存的数加上b=3的情况,即为当前情况下(a,b)的方法数.
求当b=多少的方法数,也就是求b前面有多少个数比它小。
求当c=多少的方法数,也就是求c后面有多少个数比它大。
用树状数组来做。本题n范围50000,而且每个数都不相同很关键。所以我们就开辟n个位置,一开始每个位置都是0,其实每个位置不是0就是1,因为每个数只有一个。
比如数 1 3 2 4 5
一开始 c数组 0 0 0 0 0
先统计,再输入,因为计算a[i]前面有多少比它小的数,不包括它自己,而树状数组计算和的时候,要包括它自己。
i=1, 树状数组求和前缀和 pre[1]=0 , 此时0 0 0 0 0 , 输入1,变为 1 0 0 0 0
i=2,a[2]=3,要看 3前面有多少个数,也就是看c数组的3个位置前面有多少个1,1代表已经输入,发现1 0 0 0 0前三个数只有一个1,也就是pre[2]=1 (输入的第二个数之前只有1个比它小的),输入3以后,c数组变为 1 0 1 0 0
i=3, a[3]= 2, 要看2前面有多少个数,也就是看c数组前2个位置前面有多少个1,发现10100前两个数中只有一个1,也就是pre[3]=1.
再求后缀和时,只要和上面一样倒过来输入就可以了。
在本例中最后求ans的那个for循环进行了4次: i=1时计算pre[0]*suf[1] i=2时计算(pre[0]+pre[1])*suf[2] i=3时计算(pre[0]+pre[1]+pre[2])*suf[3]
i=4时计算(pre[0]+pre[1]+pre[2]+pre[3])*suf[4]
#include <iostream>
#include <string.h>
#include <stdio.h>using namespace std;int n;int A[50001],pre[50001],suf[50001],c[50001];//pre[i] 前缀和 表示输入顺序中第i个数之前有多少个比它小的数//suf[i] 后缀和 表示输入顺序中第i个数之后有多少个比它大的数//c[i] 第i个位置代表第i个数,c[i]=0代表该数未输入,c[i]=1代表该数已经输入int lowbit(int x){ return x&(-x);}void update(int i,int x)//在第i个位置上增加x{ while(i<=n) { c[i]=c[i]+x; i=i+lowbit(i); }}int sum(int x)//c[1-i]之间的和{ int s=0; while(x>0) { s=s+c[x]; x=x-lowbit(x); } return s;}int main(){ int T; cin>>T; while(T--) { cin>>n; for(int i=1;i<=n;i++) scanf("%d",&A[i]); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { pre[i]=sum(A[i]);//统计a[i]之前有多少个比它小的数 update(A[i],1);//在a[i]位置上加1,表示已经存在 } memset(c,0,sizeof(c)); for(int i=n;i>=1;i--) { suf[i]=(n-i)-sum(A[i]); //倒着输入,第i个数后面有n-i个数,再看看这n-i个数中是不是存在比a[i]小的(即sum(a[i]), //减去它们,就是a[i]后面所有比它大的 update(A[i],1); } long long ans=0,dp=0; for(int i=1;i<=n-1;i++)//枚举c的位置 { ans=ans+dp*suf[i];//dp表示输入顺序中第i-1个数之前有多少个数比第i-1个数小,在本题中也就是比b小的个数,i是c dp=dp+pre[i]; } cout<<ans<<endl; } return 0;}
- hdu 5147 Sequence II(前缀和,后缀和)
- [ACM] hdu 5147 Sequence II (树状数组,前缀和,后缀和)
- Hdu 5147 Sequence II(树状数字 or 线段树 + 输入外挂 前缀和+后缀和)
- HDU 5147 Sequence II (线段树求前缀和、后缀和)
- hdu 5147 Sequence II(树状数组,前缀和,后缀和)
- HDU5147 Sequence II(树状数组+前缀和+后缀和)
- [HDU 5147] Sequence II (树状数组+前缀和)
- hdu 6025 gcd+前缀和+后缀和
- HDU6025 Coprime Sequence —— 前缀和 & 后缀和
- hdu 1867 最长公共前缀和后缀
- 前缀和后缀和
- 前缀++和后缀++
- 前缀和后缀表达式
- 前缀、中缀和后缀
- 前缀++和后缀++
- HDU 5147 BestCoder #23(树状数组区间 前缀和,后缀和)类似LA4329
- HDU 4436 str2int 后缀数组 字符串哈希 前缀和
- HDU 4436 str2int 后缀数组(前缀和预处理)
- 《android---获取值AndroidManifest.xml中meta-data的value》
- Elasticsearch与MongoDB 数据同步及分布式集群搭建(一)
- sql的count()函数,php怎么取他的值
- 从配置文件里读取配置信息
- Xcode找不到报错
- hdu 5147 Sequence II(前缀和,后缀和)
- scp命令的实际应用
- Struts2动态方法调用
- 《招聘一个靠谱的iOS》面试题参考答案(上)
- 统计数n阶乘中0的位数
- SpringMVC基于代码的配置方式(零配置,无web.xml)
- 随机生成id,不会重复
- 图论基础UVA10047
- 【leetcode每日一题】NO206.Reverse Linked List