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;
}
posted @ 2026-02-06 22:10  constexpr_ll  阅读(2)  评论(0)    收藏  举报