首页 > 试题广场 >

小美的序列问题

[编程题]小美的序列问题
  • 热度指数:438 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}对于给定的由 n 个整数组成的数组 \{a_1,a_2,\dots,a_n\},计算其中有多少个三元组 (i,j,k) 满足 1\leqq i < j < k \leqq na_i>a_k>a_j。例如,在数组\{4,1,2,3\} 中三元组 (1,2,3) ,(1,2,4),(1,3,4) 都是满足条件的三元组。更具体地,计算:

\displaystyle\sum\limits_{1\leqq i < j < k \leqq n}\left[a_i>a_k>a_j\right]

\hspace{15pt}请编写一个函数,计算并返回满足条件的三元组的数量。

【名词解释】
\hspace{15pt}本题公式中的中括号代表艾弗森括号,具体地,[P] = \begin{cases} 1 & \text{如果 } P \text{ 为真} \\ 0 & \text{如果 } P \text{ 为假} \end{cases}

输入描述:
\hspace{15pt}第一行输入一个整数 n \left(1\leqq n \leqq 2\times 10^5\right) 代表数组中的元素个数。
\hspace{15pt}第二行输入 n 个整数 a_1,a_2,\dots,a_n \left(-10^9\leqq a_i \leqq 10^9\right) 代表数组中的元素。


输出描述:
\hspace{15pt}输出一个整数,表示满足条件的三元组个数。
示例1

输入

5
1 5 4 2 3

输出

2

说明

\hspace{15pt}在这个样例中,满足条件的三元组有:
\hspace{23pt}\bullet\,i=2j=4k=5 构成的三元组 \{5,2,3\}
\hspace{23pt}\bullet\,i=3j=4k=5 构成的三元组 \{4,2,3\}
示例2

输入

20
-6 -9 -90 -73 89 -90 2 19 52 -16 -41 -22 85 24 -22 66 75 78 48 -36

输出

134

备注:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) (x).begin(),(x).end()
#define ceil(a,b) ((a)+(b)-1)/(b)

class Treearray
{
public:
    vector<int> t;
    int n;
    Treearray(int _n):n(_n){t.resize(n+5);}
    inline int lowbit(int x){return x&(-x);}
    void insert(int pos,int val){for(int i=pos;i<=n;i+=lowbit(i))t[i]+=val;}
    int query(int pos){int res=0;for(int i=pos;i;i-=lowbit(i))res+=t[i];return res;}
    void rangeinsert(int l,int r,int val){insert(l,val),insert(r+1,-val);}
};

void lsh(vector<int> &a)
{
//#define all(x) (x).begin(),(x).end()
    vector<int> b=a;
    sort(all(b));
    b.erase(unique(all(b)),b.end());
    for(auto &x:a)
        x=lower_bound(all(b),x)-b.begin()+1;
}

void solve()
{
	int n;
	cin>>n;
	vector<int> a(n);
	for(int i=0;i<n;i++) {
		int x;
		cin>>x;
		x += 1e9 + 5;
		a[i] = x;
	}
	lsh(a);

	n = a.size();

	// t0 统计 ai >  aj 			在[i, n]的数量
	// t1 统计 ai >= aj 			在[i, n]的数量
	// t2 统计 ai >  aj >= ak 	        在[i, n]的数量
	Treearray t0(n+10), t1(n+10), t2(n+10);

	int cnt = 0, sum = 0;
	for(int i=n-1;i>=0;i--) {
		int t = t0.query(a[i]);
		sum += t * (t - 1) / 2;
		t0.rangeinsert(a[i]+1, n+3, 1);

		int count = t1.query(a[i]);
		t1.rangeinsert(a[i], n+3, 1);

		cnt += t2.query(a[i]);
		t2.rangeinsert(a[i]+1, n+3, count);
	}

	// (ai > ak > aj)的数量总和 = (ai > ak && ai > aj)的数量总和 - (ai > aj >= ak)的数量总和
	cout << sum - cnt << '\n';
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int T=1;
	// cin>>T;
	while(T--)
		solve();
	return 0;
}

发表于 今天 01:30:46 回复(0)