AtCoder Regular Contest 119 E Pancakes

洛谷传送门

AtCoder 传送门

感觉挺典的,为啥有 2500 啊(

观察发现,反转序列对 \(\sum\limits_{i=1}^{n-1} |a'_i - a'_{i+1}|\) 影响不大。具体而言,设反转了 \(a_l \sim a_r\),记 \(s = \sum\limits_{i=1}^{n-1} |a_i - a_{i+1}|\),那么 \(s' = s - |a_{l-1} - a_l| - |a_r - a_{r+1}| + |a_l - a_{r+1}| + |a_{l-1} - a_r|\)(特判 \(l = 1 \lor r = n\))。

则现在就是要找到一组 \((l,r), 2 \le l \le r < n\),使得 \(s'\) 最小。对后两项拆绝对值之后化成三维偏序的形式,因此跑四遍 cdq 即可。

时间复杂度 \(O(n \log^2 n)\)。cdq 内使用归并排序、树状数组,可以通过。

code
// Problem: E - Pancakes
// Contest: AtCoder - AtCoder Regular Contest 119
// URL: https://atcoder.jp/contests/arc119/tasks/arc119_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 600100;
const ll inf = 0x3f3f3f3f3f3f3f3fLL;

ll n, a[maxn], b[maxn], sum, ans, lsh[maxn], tot, m;
struct node {
	ll x, y, z, op;
	node(ll a = 0, ll b = 0, ll c = 0, ll d = 0) : x(a), y(b), z(c), op(d) {}
} p[maxn], q[maxn];

inline bool cmp1(const node &a, const node &b) {
	if (a.x != b.x) {
		return a.x < b.x;
	} else if (a.y != b.y) {
		return a.y < b.y;
	} else if (a.z != b.z) {
		return a.z < b.z;
	} else {
		return a.op < b.op;
	}
}

inline bool cmp2(const node &a, const node &b) {
	if (a.x != b.x) {
		return a.x < b.x;
	} else if (a.y != b.y) {
		return a.y < b.y;
	} else if (a.z != b.z) {
		return a.z > b.z;
	} else {
		return a.op < b.op;
	}
}

inline bool cmp3(const node &a, const node &b) {
	if (a.x != b.x) {
		return a.x < b.x;
	} else if (a.y != b.y) {
		return a.y > b.y;
	} else if (a.z != b.z) {
		return a.z < b.z;
	} else {
		return a.op < b.op;
	}
}

inline bool cmp4(const node &a, const node &b) {
	if (a.x != b.x) {
		return a.x < b.x;
	} else if (a.y != b.y) {
		return a.y > b.y;
	} else if (a.z != b.z) {
		return a.z > b.z;
	} else {
		return a.op < b.op;
	}
}

namespace BIT {
	ll c[maxn];
	
	inline void init() {
		mems(c, 0x3f);
	}
	
	inline void clear(int x) {
		for (int i = x; i <= tot; i += (i & (-i))) {
			c[i] = inf;
		}
	}
	
	inline void update(int x, ll d) {
		for (int i = x; i <= tot; i += (i & (-i))) {
			c[i] = min(c[i], d);
		}
	}
	
	inline ll query(int x) {
		ll res = inf;
		for (int i = x; i; i -= (i & (-i))) {
			res = min(res, c[i]);
		}
		return res;
	}
}

void cdq1(int l, int r) {
	if (l >= r) {
		return;
	}
	int mid = (l + r) >> 1, i = l, j = mid + 1, t = 0;
	cdq1(l, mid);
	cdq1(mid + 1, r);
	while (i <= mid && j <= r) {
		if (p[i].y <= p[j].y) {
			if (p[i].op == 1) {
				BIT::update(p[i].z, -b[p[i].x - 1] - a[p[i].x] - a[p[i].x - 1]);
			}
			q[++t] = p[i++];
		} else {
			if (p[j].op == 2) {
				ans = min(ans, sum + BIT::query(p[j].z) - b[p[j].x] + a[p[j].x + 1] + a[p[j].x]);
			}
			q[++t] = p[j++];
		}
	}
	while (i <= mid) {
		if (p[i].op == 1) {
			BIT::update(p[i].z, -b[p[i].x - 1] - a[p[i].x] - a[p[i].x - 1]);
		}
		q[++t] = p[i++];
	}
	while (j <= r) {
		if (p[j].op == 2) {
			ans = min(ans, sum + BIT::query(p[j].z) - b[p[j].x] + a[p[j].x + 1] + a[p[j].x]);
		}
		q[++t] = p[j++];
	}
	for (int i = l; i <= mid; ++i) {
		if (p[i].op == 1) {
			BIT::clear(p[i].z);
		}
	}
	for (int i = 1; i <= t; ++i) {
		p[l + i - 1] = q[i];
	}
}

void cdq2(int l, int r) {
	if (l >= r) {
		return;
	}
	int mid = (l + r) >> 1, i = l, j = mid + 1, t = 0;
	cdq2(l, mid);
	cdq2(mid + 1, r);
	while (i <= mid && j <= r) {
		if (p[i].y <= p[j].y) {
			if (p[i].op == 1) {
				BIT::update(tot - p[i].z + 1, -b[p[i].x - 1] - a[p[i].x] + a[p[i].x - 1]);
			}
			q[++t] = p[i++];
		} else {
			if (p[j].op == 2) {
				ans = min(ans, sum + BIT::query(tot - p[j].z + 1) - b[p[j].x] + a[p[j].x + 1] - a[p[j].x]);
			}
			q[++t] = p[j++];
		}
	}
	while (i <= mid) {
		if (p[i].op == 1) {
			BIT::update(tot - p[i].z + 1, -b[p[i].x - 1] - a[p[i].x] + a[p[i].x - 1]);
		}
		q[++t] = p[i++];
	}
	while (j <= r) {
		if (p[j].op == 2) {
			ans = min(ans, sum + BIT::query(tot - p[j].z + 1) - b[p[j].x] + a[p[j].x + 1] - a[p[j].x]);
		}
		q[++t] = p[j++];
	}
	for (int i = l; i <= mid; ++i) {
		if (p[i].op == 1) {
			BIT::clear(tot - p[i].z + 1);
		}
	}
	for (int i = 1; i <= t; ++i) {
		p[l + i - 1] = q[i];
	}
}

void cdq3(int l, int r) {
	if (l >= r) {
		return;
	}
	int mid = (l + r) >> 1, i = l, j = mid + 1, t = 0;
	cdq3(l, mid);
	cdq3(mid + 1, r);
	while (i <= mid && j <= r) {
		if (p[i].y >= p[j].y) {
			if (p[i].op == 1) {
				BIT::update(p[i].z, -b[p[i].x - 1] + a[p[i].x] - a[p[i].x - 1]);
			}
			q[++t] = p[i++];
		} else {
			if (p[j].op == 2) {
				ans = min(ans, sum + BIT::query(p[j].z) - b[p[j].x] - a[p[j].x + 1] + a[p[j].x]);
			}
			q[++t] = p[j++];
		}
	}
	while (i <= mid) {
		if (p[i].op == 1) {
			BIT::update(p[i].z, -b[p[i].x - 1] + a[p[i].x] - a[p[i].x - 1]);
		}
		q[++t] = p[i++];
	}
	while (j <= r) {
		if (p[j].op == 2) {
			ans = min(ans, sum + BIT::query(p[j].z) - b[p[j].x] - a[p[j].x + 1] + a[p[j].x]);
		}
		q[++t] = p[j++];
	}
	for (int i = l; i <= mid; ++i) {
		if (p[i].op == 1) {
			BIT::clear(p[i].z);
		}
	}
	for (int i = 1; i <= t; ++i) {
		p[l + i - 1] = q[i];
	}
}

void cdq4(int l, int r) {
	if (l >= r) {
		return;
	}
	int mid = (l + r) >> 1, i = l, j = mid + 1, t = 0;
	cdq4(l, mid);
	cdq4(mid + 1, r);
	while (i <= mid && j <= r) {
		if (p[i].y >= p[j].y) {
			if (p[i].op == 1) {
				BIT::update(tot - p[i].z + 1, -b[p[i].x - 1] + a[p[i].x] + a[p[i].x - 1]);
			}
			q[++t] = p[i++];
		} else {
			if (p[j].op == 2) {
				ans = min(ans, sum + BIT::query(tot - p[j].z + 1) - b[p[j].x] - a[p[j].x + 1] - a[p[j].x]);
			}
			q[++t] = p[j++];
		}
	}
	while (i <= mid) {
		if (p[i].op == 1) {
			BIT::update(tot - p[i].z + 1, -b[p[i].x - 1] + a[p[i].x] + a[p[i].x - 1]);
		}
		q[++t] = p[i++];
	}
	while (j <= r) {
		if (p[j].op == 2) {
			ans = min(ans, sum + BIT::query(tot - p[j].z + 1) - b[p[j].x] - a[p[j].x + 1] - a[p[j].x]);
		}
		q[++t] = p[j++];
	}
	for (int i = l; i <= mid; ++i) {
		if (p[i].op == 1) {
			BIT::clear(tot - p[i].z + 1);
		}
	}
	for (int i = 1; i <= t; ++i) {
		p[l + i - 1] = q[i];
	}
}

void solve() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
	}
	for (int i = 1; i < n; ++i) {
		b[i] = abs(a[i] - a[i + 1]);
		sum += b[i];
	}
	ans = sum;
	for (int i = 2; i < n; ++i) {
		ans = min(ans, sum - b[i] + abs(a[1] - a[i + 1]));
	}
	for (int i = n - 1; i >= 2; --i) {
		ans = min(ans, sum - b[i - 1] + abs(a[n] - a[i - 1]));
	}
	for (int i = 1; i <= n; ++i) {
		lsh[++tot] = a[i];
	}
	sort(lsh + 1, lsh + tot + 1);
	tot = unique(lsh + 1, lsh + tot + 1) - lsh - 1;
	for (int i = 2; i < n; ++i) {
		int x = lower_bound(lsh + 1, lsh + tot + 1, a[i - 1]) - lsh;
		p[++m] = node(i, a[i], x, 1);
	}
	for (int i = 2; i < n; ++i) {
		int x = lower_bound(lsh + 1, lsh + tot + 1, a[i]) - lsh;
		p[++m] = node(i, a[i + 1], x, 2);
	}
	BIT::init();
	sort(p + 1, p + m + 1, cmp1);
	cdq1(1, m);
	sort(p + 1, p + m + 1, cmp2);
	cdq2(1, m);
	sort(p + 1, p + m + 1, cmp3);
	cdq3(1, m);
	sort(p + 1, p + m + 1, cmp4);
	cdq4(1, m);
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

posted @ 2023-05-01 20:09  zltzlt  阅读(29)  评论(0)    收藏  举报