P1966 学习笔记
省流:老师不让我们用树状数组,说什么要用分治。
首先我们得知道一个事情,设两个长度为 \(n\) 的序列 \(a\) 和 \(b\),这两个序列排序后的序列为 \(a'\) 和 \(b'\),则
\[\sum_{i=1}^{n} a_ib_i \le \sum_{i=1}^{n} a'_ib'_i
\]
即顺序之乘大于等于乱序之乘。
要求的式子:
\[\begin{align*}
\sum_{i=1}^{n} (a_i-b_i)^2&=\sum_{i=1}^{n} (a_i^2-2a_ib_i+b_i^2)\\
&=\sum_{i=1}^{n} a_i^2+\sum_{i=1}^{n} b_i^2-2\sum_{i=1}^n a_ib_i\\
&\ge \sum_{i=1}^{n} a_i^2+\sum_{i=1}^{n} b_i^2-2\sum_{i=1}^n a'_ib'_i
\end{align*}
\]
其中无论怎么交换,\(\sum_{i=1}^{n} a_i^2\) 和 \(\sum_{i=1}^{n} b_i^2\) 都是不变的,所以让原式最小,只能将 \(a\) 和 \(b\) 排完序后和最小,考虑如何交换即可。
如何交换不多讲了,mergesort 就行。
code
/**********************************************************
* Author : dingziyang888
* Website : https://www.luogu.com.cn/problem/
* Created Time :
* FileName :
* Warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* 1.MLE?
* 2.array size enough?
* 3.long long?
* 4.overflow long long?
* 5.multiple task cleaned?
* 6.freopen?
* 7.TLE?
* *******************************************************/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <iterator>
#include <map>
#include <unordered_map>
#include <queue>
#include <string>
#include <cstring>
#include <set>
#include <bitset>
#include <unordered_set>
#include <vector>
#include <deque>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <list>
#include <array>
#include <iterator>
#include <cmath>
#include <new>
#include <random>
#include <cfloat>
#include <cstdlib>
#include <climits>
#include <numeric>
#include <complex>
#include <ctime>
#include <chrono>
#include <thread>
#include <mutex>
#include <future>
#include <exception>
#include <stdexcept>
#include <cstdint>
#include <cassert>
#include <stack>
#include <cctype>
#define DEBUG
#define Ofile(s) freopen(s".in", "r", stdin), freopen (s".out", "w", stdout)
#define Cfile(s) fclose(stdin), fclose(stdout)
#define fast ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
using namespace std;
using ll = long long;
using ull = unsigned long long;
using lb = long double;
using pii = pair <int, int>;
using pil = pair <int, ll>;
using pli = pair <ll, int>
using pll = pair <ll, ll>
constexpr int mod = 1e8 - 3;
constexpr int maxn = 100005;
int n;
ll ans;
struct node{
int h, b;
bool operator < (const node &x) const{
return this->h < x.h;
}
} h1[maxn], h2[maxn];
ll fz1[maxn], fz2[maxn];
void merge_sort(int l, int r){
if (l == r)
return;
int mid = (l + r) >> 1;
merge_sort(l, mid);
merge_sort(mid + 1, r);
int i = l, j = mid + 1, k = l;
while (i <= mid && j <= r){
if (fz1[i] < fz1[j])
fz2[k] = fz1[i], ++i, ++k;
else
fz2[k] = fz1[j], ++j, ++k, ans = (ans + mid - i + 1) % mod;
}
while (i <= mid)
fz2[k] = fz1[i], ++i, ++k;
while (j <= r)
fz2[k] = fz1[j], ++j, ++k;
for (int m = l; m <= r; m++)
fz1[m] = fz2[m];
}
int main() {
fast;
freopen("std.in", "r", stdin);
freopen("std.out", "w", stdout);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> h1[i].h, h1[i].b = i;
for (int i = 1; i <= n; i++)
cin >> h2[i].h, h2[i].b = i;
sort (h1 + 1, h1 + n + 1);
sort (h2 + 1, h2 + n + 1);
for (int i = 1; i <= n; i++)
fz1[h2[i].b] = h1[i].b;
merge_sort(1, n);
cout << ans;
return 0;
}

浙公网安备 33010602011771号