链接:戳这里
World is Exploding
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
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 integers A1,A2⋯An.
1≤n≤50000
0≤Ai≤1e9
Output
For each test case,output a line contains an integer.
Sample Input
4
2 4 1 3
4
1 2 3 4
Sample Output
1
0
题意:
给出一个长度为n的整数序列,要求输出有多少个四元组{a,b,c,d}。
满足1<=a<b<=n,1<=c<d<=n,a!=b!=c!=d 且 Va<Vb && Vc>Vd
思路:
预处理出mn[i],mx[i],hmn[i],hmx[i]
mn[i]:[1,i-1]之间有多少个数比ai小
mx[i]:[1,i-1]之间有多少个数比ai大
hmn[i]:[i+1,n]之间有多少个数比ai小
hmx[i]:[i+1,n]之间有多少个数比ai大
sum[i]:表示以当前第i个数结尾,有多少对a,b满足条件。也就是前缀和mn[i]
这些都可以通过离散化+树状数组实现
接下来枚举当前ai作为Vd,那么就存在mx[i]个Vc,以及sum[n]对Va,Vb。ans+=mx[i]*sum[n]
由于答案会多算进去a=c || a=d || b=c || b=d的情况,那么枚举这四种情况减去就可以了(a=c那么必定b!=d,同理其他
a=c:ans-=hmn[i]*hmx[i]
a=d:ans-=mx[i]*hmx[i]
b=c:ans-=mn[i]*hmn[i]
b=d:ans-=mx[i]*mn[i]
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#include<bitset>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
#define INF (1ll<<60)-1
#define Max 1e9
using namespace std;
int n,m;
int a[50010],b[50010];
int num[50010];
int mn[50010],mx[50010]; /// 分别表示[1,i-1]有多少个数比ai小 大
int hmn[50010],hmx[50010]; /// 分别表示[i+1,n]有多少个数比ai小 大
int lowbit(int x){
return x&-x;
}
void Add(int x){
while(x<=m) {
num[x]++;
x+=lowbit(x);
}
}
int query(int x){
int ans=0;
while(x>=1){
ans+=num[x];
x-=lowbit(x);
}
return ans;
}
ll sum[50010];
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b;
mst(num,0);
mst(sum,0);
for(int i=1;i<=n;i++){
mn[i]=query(a[i]-1);
mx[i]=query(m)-query(a[i]);
sum[i]=sum[i-1]+mn[i]*1LL;
Add(a[i]);
//printf("%d %d\n",mn[i],mx[i]);
}
mst(num,0);
for(int i=n;i>=1;i--){
hmn[i]=query(a[i]-1);
hmx[i]=query(m)-query(a[i]);
Add(a[i]);
//printf("%d %d\n",hmn[i],hmx[i]);
}
ll ans=0;
for(int i=1;i<=n;i++){
ll num1=1LL*mx[i];
ll num2=1LL*sum[n];
ans+=num1*num2;
}
/// a=c b!=d
for(int i=1;i<=n;i++){
ll num1=hmn[i];
ll num2=hmx[i];
ans-=num1*num2;
}
/// a=d b!=c
for(int i=1;i<=n;i++){
ll num1=mx[i];
ll num2=hmx[i];
ans-=num1*num2;
}
/// b=c a!=d
for(int i=1;i<=n;i++){
ll num1=mn[i];
ll num2=hmn[i];
ans-=num1*num2;
}
/// b=d a!=c
for(int i=1;i<=n;i++){
ll num1=mx[i];
ll num2=mn[i];
ans-=num1*num2;
}
printf("%I64d\n",ans);
}
return 0;
}