【原题】
题目描述
Erwin 最近对一种叫 thair
的东西巨感兴趣。。。
在含有 nnn 个整数的序列 (a1,a2,…,an) 中,三个数被称作thair
当且仅当 (i<j<k) 且 (ai<aj<ak)。
求一个序列中 thair
的个数。
输入格式
开始一行一个正整数(n),
以后一行 (n) 个整数 (a1,a2,…,an)。
输出格式
一行一个整数表示 thair
的个数。
输入输出样例
输入 #1
4
2 1 3 4
输出 #1
2
输入 #2
5
1 2 2 3 4
输出 #2
7
说明/提示
样例2 解释
7个 thair
分别是:
- 1 2 3
- 1 2 4
- 1 2 3
- 1 2 4
- 1 3 4
- 2 3 4
- 2 3 4
数据规模与约定
- 对于 (30\%)的数据 保证 (n≤100);
- 对于 (60\%) 的数据 保证 (n≤2000);
- 对于 (100\%)的数据 保证 (1≤n≤3×10^4,0≤ai<2^{63})
【思路】
用pair存二元个数, cnt存一元个数,不断更新,题解的乘法原理没想到,惭愧。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '
'
#define lson rt << 1
#define rson rt << 1 | 1
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int maxn = 3e4 + 7;
const int maxm = 1e6 + 7;
const int mod = 1e9 + 7;
int n, m;
struct node
{
LL pair, cnt;
}tree[maxn * 4];
struct pp
{
LL pair, cnt;
}lz[maxn * 4];
LL a[maxn], b[maxn], id[maxn];
void update(int n, int index, int L, int R, int rt) {
if (L == R) {
tree[rt].cnt = n;
return;
}
int mid = (L + R) / 2;
if (index <= mid) {
update(n, index, L, mid, lson);
}
else {
update(n, index, mid + 1, R, rson);
}
tree[rt].cnt = tree[lson].cnt + tree[rson].cnt;
}
void add(int n, int index, int L, int R, int rt)
{
if (L == R)
{
tree[rt].cnt += n;
return;
}
int mid = (L + R) / 2;
if (index <= mid) add(n, index, L, mid, lson);
else add(n, index, mid + 1, R, rson);
tree[rt].cnt = tree[lson].cnt + tree[rson].cnt;
}
void push_down(int rt, int l, int r) {
if (lz[rt].cnt) {
int mid = (l + r) / 2;
lz[lson].cnt += lz[rt].cnt;
lz[rson].cnt += lz[rt].cnt;
tree[lson].cnt += 1LL * (mid - l + 1) * lz[rt].cnt;
tree[rson].cnt += 1LL * (r - mid) * lz[rt].cnt;
lz[rt].cnt = 0;
}
if (lz[rt].pair)
{
int mid = (l + r) / 2;
lz[lson].pair += lz[rt].pair;
lz[rson].pair += lz[rt].pair;
tree[lson].pair += 1LL * (mid - l + 1) * lz[rt].pair;
tree[rson].pair += 1LL * (r - mid) * lz[rt].pair;
lz[rt].pair = 0;
}
}
LL query_range(int rt, int l, int r, int L, int R) {
if (l <= L && r >= R) return tree[rt].cnt;
push_down(rt, L, R);
int mid = (L + R) / 2;
LL sum = 0;
if (mid >= l) sum += query_range(lson, l, r, L, mid);
if (mid < r) sum += query_range(rson, l, r, mid + 1, R);
return sum;
}
void add_pair(int n, int index, int L, int R, int rt)
{
if (L == R)
{
tree[rt].pair += n;
return;
}
int mid = (L + R) / 2;
if (index <= mid) add_pair(n, index, L, mid, lson);
else add_pair(n, index, mid + 1, R, rson);
tree[rt].pair = tree[lson].pair + tree[rson].pair;
}
LL query_pair(int rt, int l, int r, int L, int R)
{
if (l <= L && r >= R) return tree[rt].pair;
push_down(rt, L, R);
int mid = (L + R) / 2;
LL sum = 0;
if (mid >= l) sum += query_pair(lson, l, r, L, mid);
if (mid < r) sum += query_pair(rson, l, r, mid + 1, R);
return sum;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
LL ans = 0;
int mx = 3e4;
_rep(i, 1, n)
{
cin >> a[i];
b[i] = a[i];
}
sort(a + 1, a + n + 1);
int sz = unique(a + 1, a + n + 1) - a - 1;
mx = sz + 1;
_rep(i, 1, n)
{
id[i] = lower_bound(a + 1, a + 1 + sz, b[i]) - a;
}
_rep(i, 1, n)
{
add(1, id[i], 0, mx, 1);
ans += query_pair(1, 0, id[i] - 1, 0, mx);
LL tmp = query_range(1, 0, id[i] - 1, 0, mx);
add_pair(tmp, id[i], 0, mx, 1);
}
cout << ans << endl;
}