E - Chinese Restaurant abc268

本文介绍了一种解决n个人围坐一桌,每个人有特定菜品喜好的问题,通过分析每个人的沮丧值变化,利用算法找出调整座位使得所有人满意度最大化的方法。核心是将函数分为线性部分并独立处理系数,最终给出最小沮丧值的计算过程。

link
题意:n个人围成一桌,编号0 到 n-1, 每个人有自己喜欢的菜品,每个人收到的沮丧值是喜欢的菜品距自

思路:
考虑单独一个人的沮丧值关系,如果顺指针移动桌子,那么第(p[i] - i + n) % n 次此人沮丧值为零。
即为函数的零点。函数长这样
零点在左
或者在中间
在右边
最多分成三段(一次函数),我们将系数独立起来,然后累加。

code:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 4 * 1e5 + 10, mod = 998244353;
int n, m;
int sk[maxn], sb[maxn], p[maxn], cst[maxn];
void add(int l, int r, int k, int b) {
	if (l > r) return;
	sk[l] += k;
	sb[l] += b;
	sk[r + 1] -= k;
	sb[r + 1] -= b;
}
void add(int v) {
	if (v < n / 2) {
		add(0, v - 1, -1, v);
		add(v, v + n / 2, 1, -v);
		add(v + n / 2 + 1, n - 1, -1, n + v); // n + v 尤其精妙,分奇偶进行讨论,合并后就是n + v; 
	} else {
		add(v - n / 2, v, -1, v);
		add(v + 1, n - 1, 1, -v);
		add(0, v - n / 2 - 1, 1, n - v);
	}
}
signed main() {
	//freopen("w.ans", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	//int tt; cin >> tt; while(tt--) solve(); 
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> p[i];
		cst[i] = (p[i] - i + n) % n;
		add(cst[i]);
	}
	for (int i = 1; i < n; i++) {
		sb[i] += sb[i - 1];
		sk[i] += sk[i - 1];
	}
	int ans = 1e15, sum = 0;
	for (int i = 0; i < n; i++) {
		ans = min(ans, sk[i] * i + sb[i]);
	}
	cout << ans << endl;
	return 0;
/**
 *    Alogrithm:
 *    201
 *    author:  whc
 *    created: 2022年9月12日10:58:05 
**/
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值