1009 Triple Inversions (35 分)
解题思路:
先来真实的,一开始看到题没有思路考虑骗分,三个for,得了19分,意料中的4个T,但是19分不低了说实话,这个暴力就是白送的:
然后思考能不能多骗点分,于是想出了一个O(n^2)的写法,对于每一个值,我都是算出比他大在他左边的元素t2,以及比他小在他右边的元素t1,然后乘法组合一下得到这个值为三元逆序对中间那个值的情况贡献了t1*t2个答案。
代码:
signed main()
{
int n=rd;
for (int i = 0; i < n; i++)
{
x[i] = rd;
}
int ans=0;
for (int i = 0; i < n; i++)
{
int t1 = 0, t2 = 0;
for (int j = i+1; j < n; j++)
{
if (x[j] < x[i])t1++;
}
for (int j = 0; j < i; j++)
{
if (x[j] > x[i])t2++;
}
//cout << x[i] << ' ' << t1 << ' ' << t2 << endl;
ans += t2 * t1;
}
cout << ans << endl;
return 0;
}
很显然,还是A不了,但是也多了5分,得到了2个T:
然后思考归并排序是如何计算逆序对的,归并实际上有两个写法,一个是求左边,一个是求左边 ,刚好对应我们要的两个值。
所以归并处理出每个值比他大在他左边的元素数存在zuo数组,以及比他小在他右边的元素数存在you数组,最后枚举每个元素,用zuo[k]*you[k]即可计算处最终的ans,复杂度O(nlogn),无悬念过了(需要用long long)
代码:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define pb push_back
#define G 6.67430*1e-11
#define rd read()
#define pi 3.1415926535
using namespace std;
const ll mod = 1e9 + 7;
const int MAXN = 30000005;
const int MAX2 = 300005;
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch>'9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
ll you[200005];
ll zuo[200005];
int x[200005];
ll ans = 0;
void merge(int arr[], int s, int mid, int e)
{
vector<int> l, r;
for (int i = s; i <= mid; i++)
{
l.push_back(arr[i]);
}
for (int i = mid + 1; i <= e; i++)
{
r.push_back(arr[i]);
}
int lpos = 0, rpos = 0;
while (lpos < l.size() && rpos < r.size())
{
if (l[lpos] < r[rpos])
{
arr[s++] = l[lpos];
//ans += rpos;
you[l[lpos]]+= rpos;//比他小却排在它的右边
lpos++;
}
else
{
arr[s++] = r[rpos];
//ans += (l.size() - lpos);
zuo[r[rpos]]+= l.size() - lpos;//比他大却排在它的左边
rpos++;
}
}
while (lpos < l.size())
{
arr[s++] = l[lpos];
//ans += rpos;
you[l[lpos]] += rpos;//比他小却排在它的右边
lpos++;
}
while (rpos < r.size())
{
arr[s++] = r[rpos];
rpos++;
}
}
void mergesort(int arr[], int s, int e)
{
if (s >= e)
{
return;
}
int mid = (s + e) / 2;
mergesort(arr, s, mid);
mergesort(arr,mid + 1, e);
merge(arr, s, mid, e);
}
signed main()
{
int n=rd;
for (int i = 0; i < n; i++)
{
x[i] = rd;
}
mergesort(x, 0, n - 1);
for (int i = 0; i < n; i++)
{
ans += zuo[x[i]] * you[x[i]];
}
cout << ans;
return 0;
}