Loading

【题解】CF1615H Reindeer Games

保序回归问题,给定偏序集和 \(\{a_i\}\),求 \(\{b\}\) 使得 \(\sum|a_i-b_i|^k\) 最小。

关键结论,假设最优解是 \(\{b\}\),如果每个 \(b\) 只能是 \(x,x+\epsilon\),那么对于这个子问题的最优解是 \(\{c|c_i = b_i \le x ? x : x+\epsilon\}\)

反过来的结论同样成立,我们求得 \(\{c\}\),那么如果 \(c_i = x\)\(b_i \le x\),否则 \(b_i > x\)

所以我们可以整体二分,现在转化为如何求 \(\{c\}\),很明显每个位置只有两个取值,我们先钦定每个数为 \(x\),考虑将一些数变为 \(x+\epsilon\),那么这就是经典的最大闭合权子图,直接跑最大流即可。

#define N 1005
int n, m, a[N], u[N], ed[N], mat[N], v[N];
vector<int>c[N];
int h[N], tot, d[N], s, t, cur[N];
queue<int>q;
struct edge{int to, nxt, cap;}e[N << 3];
void add(int x,int y,int cap){
	e[++tot].nxt = h[x], h[x] = tot, e[tot].to = y, e[tot].cap = cap;
	e[++tot].nxt = h[y], h[y] = tot, e[tot].to = x, e[tot].cap = 0;
}
bool bfs(){
	rp(i, t)d[i] = 0, cur[i] = h[i];
	d[s] = 1; q.push(s);
	while(!q.empty()){
		int x = q.front(); q.pop();
		for(int i = h[x]; i; i = e[i].nxt)if(e[i].cap && !d[e[i].to])
			d[e[i].to] = d[x] + 1, q.push(e[i].to);
	}
	return d[t] > 0;
}
int dfs(int x,int flow){
	if(t == x)return flow;
	int res = flow;
	for(int &i = cur[x]; i; i = e[i].nxt)if(d[e[i].to] == d[x] + 1 && e[i].cap){
		int now = dfs(e[i].to, min(res, e[i].cap));
		if(!now)d[e[i].to] = 0;
		else e[i].cap -= now, e[i ^ 1].cap += now, res -= now;
		if(!res)return flow;
	}
	return flow - res;
}
void solve(int l,int r,int L,int R){
	if(l > r)return;
	//cout << "ss " << l << " " << r << " " << L << " " << R << endl;
	if(L == R){rep(i, l, r)ed[u[i]] = L; return;}
	int mid = (L + R) >> 1;
	s = r - l + 2, t = s + 1;
	tot = 1; rp(i, t)h[i] = 0;
	rep(i, l, r){
		//int val = mid >= a[u[i]] ? -1 : 1;
		if(mid < a[u[i]])add(s, i - l + 1, 1);
		else add(i - l + 1, t, 1);
		mat[u[i]] = i - l + 1;
	}
	rep(i, l, r)go(y, c[u[i]])if(mat[y])add(i - l + 1, mat[y], inf);
	rep(i, l, r)mat[u[i]] = 0;
	while(bfs())dfs(s, inf);
	int ls = l, rs = r;
	rep(i, l, r){
		if(d[i - l + 1] > 0)v[rs--] = u[i];
		else v[ls++] = u[i];
	}
	rep(i, l, r)u[i] = v[i];
	solve(l, ls - 1, L, mid), solve(ls, r, mid + 1, R);
}
int main() {
	read(n, m); int r = 1;
	rp(i, n)read(a[i]), u[i] = i, cmx(r, a[i]);
	rp(i, m){
		int x, y;
		read(x, y);
		c[x].pb(y);
	}
	solve(1, n, 1, r);
	rp(i, n)printf("%d ", ed[i]); el;
	return 0;
}
posted @ 2022-03-13 16:52  7KByte  阅读(97)  评论(0编辑  收藏  举报