P1966 火柴排队
题意:有两列火柴,各有各的高度,两两高度不同,每次只能交换相邻的数,问最少交换多少次,使得 ∑ ( a i − b i ) 2 \sum (a_i-b_i)^2 ∑(ai−bi)2最小。
解法:离散化+树状数组!
因为数据各不相同,可以想到最优的情况一定是最小的对应第二组的最小的,次小的对应次小的,…,那么可以清楚这题跟数字的大小无关,只和相对大小有关,那么能想到离散化,这里是离散化的两种方法,刚开始理解的时候,会错了意思,以为离散化以后,只是把离散化后的值采取p[a[i]]=b[i],所以采用了第二种方法,但是第二种方法离散化以后,不能访问到原数组的下标。仔细想了一下,因为是需要求交换次数的,要展现出相对大小的同时,还要知道原数组中第一小的值位置在哪,第二小的值位置在哪,那么第二种离散化方式用在这题就是错的(只过了一个点)。
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#include <bitset>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define PI acos(-1)
#define eps 1e-4
#define rint register int
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<double, int> pdi;
typedef pair<LL, LL> pll;
typedef pair<double, double> pdd;
typedef map<int, int> mii;
typedef map<LL, int> mli;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
int f = 1; res = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0'; c = getchar(); }
res *= f;
}
const int ne[8][2] = {
1, 0, -1, 0, 0, 1, 0, -1, -1, -1, -1, 1, 1, -1, 1, 1};
const LL INF = 1e18;
const int N = 1e5+10;
const LL Mod = 99999997;
const int M = 110;
LL tmp[N], c[N];
int n, cnt;
LL tr[N];
int lowbit(int x) {
return x & -x; }
void upd(int p, LL d) {
for( ; p <= n; p += lowbit(p) ) tr[p] = (tr[p] + d) % Mod;
}
LL que(int p) {
LL r = 0;
for( ; p > 0; p -= lowbit(p) ) r = (r + tr[p]) % Mod;
return r;
}
struct xx {
int v, id;
bool operator < (const xx &c) const {
return v < c.v;
}
}a[N], b[N];
int main() {
scanf("%d", &n);
_rep(1, n, i) {
scanf("%lld", &a[i].v); a[i].id = i; }
_rep(1, n, i) {
scanf("%lld", &b[i].v); b[i].id = i; }
sort(a+1, a+n+1); sort(b+1, b+n+1);
_rep(1, n, i) c[a[i].id] = b[i].id;
LL ans = 0;
_rep(1, n, i) {
upd(c[i], 1); ans = (ans + i - que(c[i]))%Mod;
}
printf("%lld\n", ans);
return 0;
}