萌新求助,关于二分
查看原帖
萌新求助,关于二分
173660
zhoukangyang楼主2021/2/8 18:02

为什么 wqswqs 二分需要选择 决策点最前面的节点啊qaq

蒟蒻的代码:

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++)
#define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
#define ll long long
#define ull unsigned long long
#define db double
#define ldb long double
#define pii pair<int, int>
#define mkp make_pair
#define sz(x) ((int) x.size())
#define be(x) x.begin()
#define en(x) x.end()
using namespace std;
const int N = 5e5;
int n, m, cnt[N];
ll dp[N], a[N], w[N], ans;
ll getval(int l, int r) {
	int mid = (l + r) >> 1; 
	return w[l - 1] + w[r] - w[mid] * 2 - a[mid] * (l + r - mid * 2 - 1);
}
int q[N], head, tail, las[N];
int get(int x, int y) { // y 更优的区间
	int l = 1, r = n, ans = n + 1;
	while(l <= r) {
		int mid = (l + r) >> 1;
		if(dp[y] + getval(y + 1, mid) < dp[x] + getval(x + 1, mid)) ans = mid, r = mid - 1;
		else l = mid + 1;
	}
	return ans;
}
int solve(ll x) {
	memset(dp, 0x3f, sizeof(dp));
	dp[0] = 0, cnt[0] = 0;
	head = tail = 1, las[1] = n + 1; // [las_{i - 1}, las_i)
	L(i, 1, n) {
		while(head < tail && las[head] <= i) ++head;
		dp[i] = dp[q[head]] + x + getval(q[head] + 1, i), cnt[i] = cnt[q[head]] + 1;
		while(head < tail && get(q[tail], i) <= las[tail - 1]) --tail;
		las[tail] = get(q[tail], i), q[++tail] = i, las[tail] = n + 1;
	}
	return cnt[n];
}
void Main() {
	cin >> n >> m;
	L(i, 1, n) cin >> a[i], w[i] = w[i - 1] + a[i];
	ll l = 0, r = getval(1, n);
	while(l <= r) {
		ll mid = (l + r) >> 1;
		if(solve(mid) <= m) ans = dp[n] - mid * m, r = mid - 1;
		else l = mid + 1;
	}
	cout << ans << endl;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	Main();
	return 0;
}

get 函数中:

if(dp[y] + getval(y + 1, mid) < dp[x] + getval(x + 1, mid)) ans = mid, r = mid - 1;

改成

if(dp[y] + getval(y + 1, mid) <= dp[x] + getval(x + 1, mid)) ans = mid, r = mid - 1;

就会 WA2020 分。

这是为什么啊 /kel /kel

2021/2/8 18:02
加载中...