(one data one problem)hdu-5792 World is Exploding (树状数组)
来源:互联网 发布:数据地图网 编辑:程序博客网 时间:2024/06/03 11:18
题目链接:点击打开链接
Problem Description
Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad .
Input
The input consists of multiple test cases.
Each test case begin with an integer n in a single line.
The next line contains n integersA1,A2⋯An .
1≤n≤50000
0≤Ai≤1e9
Each test case begin with an integer n in a single line.
The next line contains n integers
Output
For each test case,output a line contains an integer.
Sample Input
42 4 1 341 2 3 4
Sample Output
10题目大意:给出一个长为n的序列,问有多少四元组(a,b,c,d)满足a!=b!=c!=d,1<=a<b<=n
题解:
首先要找到这样的四元组是怎么来的,可以先把四元组拆分一下那就是两个二元组,二元组就好求了。就是求一个两个逆序数。那么一个升序,一个降序的二元组的个数相乘就是四元组的了。但是这样乘的话肯定会有用到重复的数字的。因为根据题目要求可以在求逆序数的时候让a!=b。所以在乘的过程中相等会有a=c,a=d,b=c,b=d这四种情况。那么怎么去重以及怎么求呢?
对于第i个数,可以求出它的左面比他大的数的个数,左面比他小的个数,右面比他小的和比他大的。在求升序对的时候就是找出每个比i小的加起来就可以了。那么降序就是左面比他大的呗!相乘就是总的四元组的个数(没有去重的情况下的)。
现在去重。比如先看一下当a==c的时候,那么也就是a和c此时是一个数,那么看看b和d放在什么位置呢?
因为b>a,所以b在a的右面,d要大于c所以d也要在c的右面。也就是a(c),(b,d),回到题意,如果把a(c)作为第i个值得话。Ai<Ab(升序),,Ai>Ad(降序)。可以看出这是重复的部分。要把它去掉,也就是把i的右面比它大的(以i升序的部分)乘以 右面比它小的(以i降序的部分)。同理其他的也只这样处理。
#include <iostream>#include <bits/stdc++.h>using namespace std;typedef long long LL;LL a[50050],c[50050];LL b[50050];LL lmx[50050],rmx[50050],lmn[50050],rmn[50050];map<LL,LL>mp;void add(LL i,LL x,LL n){ while(i<=n) { c[i]+=x; i+=i&(-i); }}LL sum(LL i){ LL s=0; while(i>=1) { s+=c[i]; i-=i&(-i); } return s;}int main(){ LL n; while(~scanf("%lld",&n)) { LL ans=0; mp.clear(); for(LL i=1;i<=n;i++) { scanf("%lld",&a[i]); b[i]=a[i]; //if(!mp[a[i]])mp[a[i]]=++ans; } sort(b+1,b+n+1); for(LL i=1;i<=n;i++) { if(!mp[b[i]])mp[b[i]]=++ans; } for(LL i=1;i<=n;i++) { a[i]=mp[a[i]]; //cout<<a[i]<<" "; } //cout<<endl; LL oto=0; memset(c,0,sizeof(c)); for(LL i=1;i<=n;i++) { lmn[i]=sum(a[i]-1); lmx[i]=sum(ans)-sum(a[i]); oto+=lmn[i]; add(a[i],1,ans); //cout<<lmn[i]<<" "<<lmx[i]<<endl; } //cout<<"---------------"<<endl; memset(c,0,sizeof(c)); for(LL i=n;i>=1;i--) { rmn[i]=sum(a[i]-1); rmx[i]=sum(ans)-sum(a[i]); add(a[i],1,ans); //cout<<rmn[i]<<" "<<rmx[i]<<endl; } //cout<<"-------------------"<<endl; LL ant=0; for(LL i=1;i<=n;i++) { ant+=oto*lmx[i]; } ///a=c; for(LL i=1;i<=n;i++) { ant-=(rmx[i]*rmn[i]); } ///a=d; for(LL i=1;i<=n;i++) { ant-=(rmx[i]*lmx[i]); } ///b=c; for(LL i=1;i<=n;i++) { ant-=(lmn[i]*rmn[i]); } ///b=d; for(LL i=1;i<=n;i++) { ant-=(lmn[i]*lmx[i]); } printf("%lld\n",ant); } return 0;}
0 0
- (one data one problem)hdu-5792 World is Exploding (树状数组)
- hdu 5792 World is Exploding 树状数组
- HDU-5792-World is Exploding-树状数组
- HDU 5792 World is Exploding (树状数组逆序对)
- HDU-5792-World is Exploding(树状数组+离散化)
- hdu 5792 World is Exploding (树状数组)
- HDU 5792 World is Exploding(树状数组)
- HDU 5792 World is Exploding(树状数组+离散化)
- hdu 5792 World is Exploding 离散化+树状数组
- HDU-5792 World is Exploding(思维、树状数组+离散化)
- HDU 5792 World is Exploding (容斥原理+离散化+树状数组)
- HDU 5792 多校5 World is Exploding(树状数组,离散化,组合数学)
- hdu 5792 World is Exploding(2016 Multi-University Training Contest 5——树状数组)
- (HDU 5792)World is Exploding <树状数组+去重> 多校训练5
- HDU 5792 World is Exploding 2016多校赛第五场 树状数组+容斥原理
- HDU 5792 World is Exploding(BIT)
- HDU 5792 World is Exploding
- HDU 5792 World is Exploding
- 剑指offer-7.斐波那契数列
- socket编程入门(二)
- AndroidStudio实现变种Builder模式的自动化生成
- Iterator接口
- 对计科核心课程的关系的总结
- (one data one problem)hdu-5792 World is Exploding (树状数组)
- Qt-QML-Repeater-导航条
- Linux下移植LCD驱动
- Ex5: Projective Transform & Image Morphing
- bzoj3365: [Usaco2004 Feb]Distance Statistics 路程统计
- HDU-1022 Train Problem I
- Linux下用户组、文件权限详解
- ROS知识(3)----功能包package编译的两种方式
- C++输入输出的格式控制2