hdu 5147
2014-12-22 21:48
465 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5147
太久没做这种题啦,,而且本来树状数组理解的不好。。结果卡了好久。。- -
这道题目教我们求的是一个符合条件的index (a,b,c,d) 要符合a<b<c<d&&Aa<Ab,Ac<Ad。
正解是枚举c,求得c之前符合条件的a,b对数x,再求得比c大的个数d为y,那么答案就是x*y;
我们先正序求树状数组,用数组f[i]代表出现在i之前,且比A[i]小的数字的个数。
再逆序求,用数组g[i]代表出现在i之后,且比A[i]大的数字的个数。
这样,我们用sum保存f[0].+....f[i-1]的和,那么此时的答案就是sum*g[i],因为g[i]代表的意思上面也说过,也就是A[i]与其后面能够成符合条件的c,d(c<d&&Ac<Ad),
sum就是i之前(注意,不包含i !!)符合条件的a,b的对数,这就是关键。
太久没做这种题啦,,而且本来树状数组理解的不好。。结果卡了好久。。- -
这道题目教我们求的是一个符合条件的index (a,b,c,d) 要符合a<b<c<d&&Aa<Ab,Ac<Ad。
正解是枚举c,求得c之前符合条件的a,b对数x,再求得比c大的个数d为y,那么答案就是x*y;
我们先正序求树状数组,用数组f[i]代表出现在i之前,且比A[i]小的数字的个数。
再逆序求,用数组g[i]代表出现在i之后,且比A[i]大的数字的个数。
这样,我们用sum保存f[0].+....f[i-1]的和,那么此时的答案就是sum*g[i],因为g[i]代表的意思上面也说过,也就是A[i]与其后面能够成符合条件的c,d(c<d&&Ac<Ad),
sum就是i之前(注意,不包含i !!)符合条件的a,b的对数,这就是关键。
/* * ThinkingLion.cpp * * Created on: 2014年12月22日 * Author: dell */ #include<stdio.h> #include<iostream> #include<string> #include<string.h> #include<algorithm> #include<iomanip> #include<vector> #include<time.h> #include<queue> #include<stack> #include<iterator> #include<math.h> #include<stdlib.h> #include<limits.h> #include<map> //#define ONLINE_JUDGE #define eps 1e-8 #define INF 0x7fffffff #define FOR(i,a) for((i)=0;i<(a);(i)++) #define MEM(a) (memset((a),0,sizeof(a))) #define sfs(a) scanf("%s",a) #define sf(a) scanf("%d",&a) #define sfI(a) scanf("%I64d",&a) #define pf(a) printf("%d\n",a) #define pfI(a) printf("%I64d\n",a) #define pfs(a) printf("%s\n",a) #define sfd(a,b) scanf("%d%d",&a,&b) #define sft(a,b,c)scanf("%d%d%d",&a,&b,&c) #define for1(i,a,b) for(int i=(a);i<b;i++) #define for2(i,a,b) for(int i=(a);i<=b;i++) #define for3(i,a,b)for(int i=(b);i>=a;i--) #define MEM1(a) memset(a,0,sizeof(a)) #define MEM2(a) memset(a,-1,sizeof(a)) const double PI=acos(-1.0); template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} template<class T> inline T Min(T a,T b){return a<b?a:b;} template<class T> inline T Max(T a,T b){return a>b?a:b;} using namespace std; #define ll __int64 int n,m; #define N 50005 int a ; ll c ,f ,g ; //f[i]代表出现在i之前且比a[i]小的数,g[i]代表出现在i之后且比a[i]大的数 int lowbit(int x){ return x&(-x); } int sum(int x){ int res = 0; while(x>0){ res += c[x]; x-=lowbit(x); } return res; } void upDate(int x,int d){ while(x<=n){ c[x] += d; x += lowbit(x); } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif int t; sf(t); while(t--){ sf(n); memset(c,0,sizeof c); for(int i=1;i<=n;i++){ sf(a[i]); } for(int i=1;i<=n;i++){ // upDate(a[i],1); f[i] = sum(a[i]) - 1; //-1是减去本身,统计比a[i]小的数字的个数 } memset(c,0,sizeof c); for(int i=n;i>=1;i--){ //reverse upDate(a[i],1); g[i] = n-i+1-sum(a[i]); //统计出现在a[i]后比a[i]大的数字的个数 } ll sum = 0; ll ans = 0; for(int i=1;i<=n;i++){ ans += sum*g[i]; //注意,这里sum的值其实是f[1]+...f[i-1]的值, //这样sum就是i之前符合条件的a,b的对数,g[i]就是比a[i]大的个数,即d的个数,也就是c,d的对数,sum*g[i]就是符合条件的a,b,c,d的数量 sum += f[i]; } printf("%I64d\n",ans); } return 0; }
相关文章推荐
- hdu 5147 树状数组
- hdu 5147 Sequence II 树状数组
- hdu 5147 Sequence II BestCoder Round #23 1002
- HDU 5147 Sequence II (线段树求前缀和、后缀和)
- hdu 5147 Sequence II (树状数组 求逆序数)
- HDU 5147 Sequence II 树状数组
- hdu 5147 树状数组
- hdu 5147 Sequence II BestCoder #23 —树状数组
- [ACM] hdu 5147 Sequence II (树状数组,前缀和,后缀和)
- HDU 5147 树状数组
- 杭电hdu 5147 Sequence II (树状数组)
- hdu 5147 Sequence II(树状数组)
- hdu 5147——Sequence II
- hdu 5147 Sequence II
- hdu 5147 Sequence II
- Hdu 5147 Sequence II(树状数字 or 线段树 + 输入外挂 前缀和+后缀和)
- HDU 5147 Harry And Magic Box dp+组合数
- hdu 5147 Sequence II(树状数组,前缀和,后缀和)
- HDU 5147 Sequence II 【树状数组维护信息 + 后缀和思想】
- HDU 5147 BestCoder #23(树状数组区间 前缀和,后缀和)类似LA4329