码迷,mamicode.com
首页 > 移动开发 > 详细

codeforces 1513F. Swapping Problem

时间:2021-04-20 15:01:50      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:ons   交换   ring   开始   min   swa   time   i++   ssi   

You are given 2 arrays a and b, both of size n. You can swap two elements in b at most once (or leave it as it is), and you are required to minimize the value

\[\sum_i|ai?bi|. \]

Find the minimum possible value of this sum.
大意:有两个大小为\(n\)的数组\(a\)\(b\),交换数组\(b\)中的任意两个元素至多1次,使\(\sum_i|ai?bi|\)最小。\(n\le 2\cdot 10^5\)\(a_i,b_i\le10^9\)


设一开始\(\sum_i|ai?bi|=tot\),交换\(b_i,b_j\),答案变为

\[\sum_i|ai?bi|-(|a_i-b_i|+|a_j-b_j|-|a_i-b_j|-|a_j-b_i|), \]

所以最大化\(|a_i-b_i|+|a_j-b_j|-|a_i-b_j|-|a_j-b_i|\)就可以了。

固定\(i\)。为了拆掉绝对值符号,对\(a_j,b_i\)\(b_j,a_i\)的大小关系分成\(2\times 2=4\)类,然后分别处理。

例如,当\(a_j\ge b_i\)\(b_j\le a_i\)

\[|a_j-b_j|-|a_i-b_j|-|a_j-b_i|=(|a_j-b_j|-a_j+b_j)-a_i+b_i, \]

对符合条件的\(j\)求括号内的部分的最大值,最后加上和\(i\)有关的部分就可以了。

对其它情况,处理方法几乎没有区别。我用分治方法离线查找最大值,一共需要做四次,实现起来有点繁琐。。还好代码不算长qwq

#include <cstdlib>
#include <iostream>
#include <cstdio>
#include <math.h>
#include <cstring>
#include <time.h>
#include <complex>
#include <algorithm>
#include <queue>
#include <stack>
#include <unordered_map>
#include <set>
#include <bitset>

#pragma warning(disable:4996)
#define PII std::pair<long long, long long>
#define PTT std::pair<tree *, tree *>

template<typename T> T min(T x, T y)
{
	return x < y ? x : y;
}
template<typename T> T max(T x, T y)
{
	return x > y ? x : y;
};

const long long INF = 200000000500000;//;// autojs.org
const long long mod = 998244353;//1000000007;// 
const int MAXN = 400005;

struct data {
	int id;
	PII p;
	data(int ID = 0, PII P = { 0,0 }) { id = ID, p = P; }
};
struct Solve {
	int N;
	data a[MAXN];
	bool (*cmp1)(const data &, const data &);
	bool (*cmp2)(const data &, const data &);
	long long (*val)(data &);
	long long ans[MAXN];

	Solve() {}
	Solve(long long *x, long long *y, int n, bool (*c1)(const data &, const data &)
		, bool (*c2)(const data &, const data &), long long (*va)(data &))
	{
		cmp1 = c1, cmp2 = c2, val = va;
		N = 2 * n;
		for (int i = 1; i <= n; i++)
			a[i] = data(i, { x[i], y[i] });
		for (int i = n + 1; i <= 2 * n; i++)
			a[i] = data(i, { y[i - n], x[i - n] });
		std::sort(a + 1, a + N + 1, cmp1);
		for (int i = 1; i <= N; i++)
			ans[i] = -INF;
	}
	void solve(int L, int R)
	{
		static data tmp[MAXN];
		if (L == R)
			return;
		int mid = (L + R) / 2;
		solve(L, mid);
		solve(mid + 1, R);
		int i = L, j = mid + 1, k = L;
		long long mx = -INF;
		while (k <= R)
		{
			if (i <= mid && (j > R || cmp2(a[i], a[j])))
			{
				if (a[i].id <= N / 2)
					mx = max(mx, val(a[i]));
				tmp[k++] = a[i++];
			}
			else
			{
				ans[a[j].id] = max(ans[a[j].id], mx);
				tmp[k++] = a[j++];
			}
		}
		for (int i = L; i <= R; i++)
			a[i] = tmp[i];
	}
};

long long mabs(long long x) { return x > 0 ? x : -x; }
bool cmp11(const data &x, const data &y) { if (x.p.first == y.p.first)return x.id < y.id; return x.p.first > y.p.first; }
bool cmp12(const data &x, const data &y) { if (x.p.second == y.p.second)return x.id < y.id; return x.p.second < y.p.second; }
bool cmp21(const data &x, const data &y) { if (x.p.first == y.p.first)return x.id < y.id; return x.p.first > y.p.first; }
bool cmp22(const data &x, const data &y) { if (x.p.second == y.p.second)return x.id < y.id; return x.p.second > y.p.second; }
bool cmp31(const data &x, const data &y) { if (x.p.first == y.p.first)return x.id < y.id; return x.p.first < y.p.first; }
bool cmp32(const data &x, const data &y) { if (x.p.second == y.p.second)return x.id < y.id; return x.p.second > y.p.second; }
bool cmp41(const data &x, const data &y) { if (x.p.first == y.p.first)return x.id < y.id; return x.p.first < y.p.first; }
bool cmp42(const data &x, const data &y) { if (x.p.second == y.p.second)return x.id < y.id; return x.p.second < y.p.second; }
long long val1(data &x) { return mabs(x.p.first - x.p.second) - x.p.first + x.p.second; }
long long val2(data &x) { return mabs(x.p.first - x.p.second) - x.p.first - x.p.second; }
long long val3(data &x) { return mabs(x.p.first - x.p.second) + x.p.first - x.p.second; }
long long val4(data &x) { return mabs(x.p.first - x.p.second) + x.p.first + x.p.second; }

int N;
long long a[MAXN], b[MAXN], tot;
Solve S[4];

void init()
{
	scanf("%d", &N);
	for (int i = 1; i <= N; i++)
		scanf("%lld", a + i);
	for (int i = 1; i <= N; i++)
		scanf("%lld", b + i), tot += mabs(a[i] - b[i]);
	S[1 - 1] = Solve(a, b, N, cmp11, cmp12, val1);
	S[2 - 1] = Solve(a, b, N, cmp21, cmp22, val2);
	S[3 - 1] = Solve(a, b, N, cmp31, cmp32, val3);
	S[4 - 1] = Solve(a, b, N, cmp41, cmp42, val4);
}
void solve()
{
	const int c[4][2] = { {-1,1},{1,1},{1,-1},{-1,-1} };
	long long ans = 0;
	for (int i = 0; i < 4; i++)
	{
		S[i].solve(1, S[0].N);
		for (int j = 1; j <= N; j++)
			ans = max(ans, S[i].ans[j + N] + mabs(a[j] - b[j])
				+ c[i][0] * a[j] + c[i][1] * b[j]);
	}
	printf("%lld\n", tot - ans);
}

int main()
{
	init();
	solve();

	return 0;
}

codeforces 1513F. Swapping Problem

标签:ons   交换   ring   开始   min   swa   time   i++   ssi   

原文地址:https://www.cnblogs.com/blogofddw/p/14673297.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!