首页 > 其他分享 >CF1861F Four Suits【网络流,贪心】

CF1861F Four Suits【网络流,贪心】

时间:2023-11-06 16:35:26浏览次数:35  
标签:limits int mid sum 卡牌 Suits Four CF1861F mx

有 \(n\) 个人,\(4\) 种不同的卡牌,初始第 \(i\) 个人有 \(a_{i,j}\) 张第 \(j\) 种卡牌。

你是局外人,手里第 \(j\) 种卡牌有 \(b_j\) 个,你现在要把你的卡牌分给这 \(n\) 个人,使得分完之后每个人手里的卡牌总数相等,保证有解。

第 \(i\) 个人最终的分数是手里每种卡牌的数量的最大值。分数最高的那个人如果分数为 \(x\),除了他之外分数最高的人的分数为 \(y\),那么他会获得 \(x-y\) 的喜悦程度(如果存在两个分数最高的,那么他们的喜悦度都是 \(0\)),其他人会获得 \(0\) 的喜悦程度。

对于每个人,算出他最大的可能的喜悦程度。

\(2 \le n \le 5 \times 10^4\),\(0 \le b_j,a_{i,j} \le 10^6\)。


设 \(M\) 为最终每个人的总卡牌数,\(c_i = M - \sum\limits_j a_{i,j}\) 表示第 \(i\) 个人需要收到多少张牌。

考虑怎么计算一个人 \(i\) 的答案,假设我们希望第 \(i\) 个人最多的卡牌为类型 \(j\),那么通过调整可以证明,最优策略一定是尽可能将类型 \(j\) 的卡牌给 \(i\)。显然我们最多能给 \(\min(b_j,c_i)\) 个卡牌 \(j\) 给第 \(i\) 个人。这样第 \(i\) 个人每种卡牌个数的最大值就确定了,我们的目标变为让另外 \(n-1\) 个人每种卡牌个数的最大值尽可能小。考虑二分答案 \(mid\),用网络流模型检验 \(mid\) 是否可行:

新建源点 \(S\) 和汇点 \(T\),以及 \(x_1 \sim x_4\),\(y_1 \sim y_n\),连边:

  • \(S \to x_i\),容量 \(b_i\)。
  • \(x_i \to y_j(j \neq i)\),容量 \(mid - a_{j,k}\)。
  • \(y_j \to T(j \neq i)\),容量 \(c_j\)。

最后检验最大流是否为 \(\sum\limits_{i\ne j}c_j\) 即可。

然而每次检验都建一次图是没法接受的。考虑最大流最小割定理,只需要判断是否所有割的权值都 \(\geq \sum\limits_{i\ne j}c_j\) 即可。我们枚举哪些与源点相连的边没被割掉,那么割掉剩余的边的代价就是 \(\sum\limits_{i \neq j}\min(c_j,\sum\limits_{x \in S} mid - a_{j,x})\)。割掉与 \(S\) 相连的边的代价是 \(\sum\limits_{x\notin S}b_x\)。后者容易计算,前者可以对于每个 \(S\) 差分预处理出每个 \(mid\) 对应的值,就可以快速检验了。总时间复杂度 \(\mathcal{O}(n \cdot 4^2 \cdot 2^4 \log V + 2^4 \cdot V)\)。

code
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
constexpr int N = 5e4 + 5, K = 4e6 + 5;
bool Mbe;
int n, M, mx1, mx2;
int a[N][4], b[4], mx[N], c[N], val[1 << 4][N], cnt[1 << 4][K];
LL sumc, sum[1 << 4][K];
bool Med;
int main() {
//	fprintf(stderr, "%.9lf\n", 1.0 * (&Mbe - &Med) / 1048576.0);
	ios :: sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < 4; j++) cin >> a[i][j], M += a[i][j], mx[i] = max(mx[i], a[i][j]);
		mx2 = max(mx2, min(mx1, mx[i]));
		mx1 = max(mx1, mx[i]);
	}
	for (int i = 0; i < 4; i++) cin >> b[i], M += b[i];
	M /= n;
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < 4; j++) c[i] += a[i][j];
		c[i] = M - c[i], sumc += c[i];
		for (int s = 0; s < 1 << 4; s++)
			for (int j = 0; j < 4; j++) {
				if (s & (1 << j)) val[s][i] += a[i][j];
			}
	}
	for (int s = 1; s < 1 << 4; s++) {
		for (int i = 1; i <= n; i++) {
			int x = (val[s][i] + c[i]) / __builtin_popcount(s) + 1;
			sum[s][0] -= val[s][i], cnt[s][0]++;
			sum[s][x] += val[s][i], cnt[s][x]--;
			sum[s][x] += c[i];
		}
		for (int i = 1; i <= M; i++) sum[s][i] += sum[s][i - 1], cnt[s][i] += cnt[s][i - 1];
	}
	int ans;
	for (int i = 1; i <= n; i++) {
		ans = 0;
		int lim = mx[i] == mx1 ? mx2 : mx1;
		for (int j = 0; j < 4; j++) {
			int cur = min(c[i], b[j]);
			int L = lim, R = M, res = M;
			b[j] -= cur;
			auto check = [&](int m) {
				for (int s = 0; s < 1 << 4; s++) {
					LL cut = sum[s][m] + 1LL * cnt[s][m] * __builtin_popcount(s) * m;
					cut -= min(c[i], __builtin_popcount(s) * m - val[s][i]);
					for (int k = 0; k < 4; k++) if (!(s & (1 << k))) cut += b[k];
					if (cut < sumc - c[i]) return false;
				}
				return true;
			};
			while (L <= R) {
				int m = L + R >> 1;
				if (check(m)) R = m - 1, res = m;
				else L = m + 1;
			}
			ans = max(ans, a[i][j] + cur - res), b[j] += cur;
		}
		cout << ans << " ";
	}
//	cerr << 1e3 * clock() / CLOCKS_PER_SEC << "ms\n";
	return 0; 
}

标签:limits,int,mid,sum,卡牌,Suits,Four,CF1861F,mx
From: https://www.cnblogs.com/came11ia/p/17812976.html

相关文章

  • Linux_JXNUFourWeek_Linux过滤器
    frompixivgrep行过滤grep匹配内容源输入grepandAndfile.txt//这条命令将会匹配Andfile.txt中文本的全部包含and的行grep-iandAndfile.txt//-i会忽略大小写grep-nandAndfile.txt//-n会显示出匹配出来的行的行号grep-vandAndfile.txt//-v是反向,即这里表......
  • 7月4日 Fourth Point !!
    FourthPoint!!#include<iostream>usingnamespacestd;classpoint{public:doublex;doubley;boolequals(constpoint&p){if(p.x==x&&p.y==y)returntrue;returnfalse;}};intmain(){pointa,b......
  • 分布理论读书笔记三:Fourier变换
    5.\(\mathscr{S}\)上的傅里叶变换5.1.Schwartz函数空间\(\mathscr{S}(\mathbb{R}^n)\).定义1:设\(\varphi\inC^{\infty}(\mathbb{R}^n)\),如果对任意非负多重指标\(\alpha,p\)都有:\[\lim_{|x|\to\infty}|x^{\alpha}\partial^p\varphi|=0\qquad(eq1)\]在\(\mathbb{R}......
  • R语言代做编程辅导ASSIGNMENT FOUR - RANDOM GRAPHS(附答案)
    全文链接:https://tecdat.cn/?p=33183PROBLEM1)CreatingRandomAdjacencyMatricesScriptName:adjMatrixInput:n...Thenumberofverticesinthegraphp...Probablitytwoverticesareconnectedplot...whetherornotthematrixshouldbeplottedasagraph......
  • Fourier Analysis and Nonlinear Partial Differential Equations 阅读笔记 (第一章)
    实分析基础Holder与卷积不等式首先从经典的Holder不等式入手.命题:经典情况下的Holder不等式设\((X,\mu)\)是测度空间,\((p,q,r)\in[1,\infty]^3\)满足\[\frac{1}{p}+\frac{1}{q}=\frac{1}{r}\]如果\((f,g)\inL^p(X,\mu)\timesL^q(X,\mu)\),则\(f\cdotg\inL^r(X,\m......
  • Codeforces 1566G - Four Vertices(线段树分治)
    交了整整2页,本来想用随机化卡过去的,后来发现我的实现跑得太慢就写正常做法了。首先发现最优答案对应的四个点只可能有以下两种可能:\(a,b\)间有边,\(c,d\)间有边,此时答案是\(a,b\)边权值加\(c,d\)边权值。\(a\)与\(b,c,d\)三个点间都有边,此时答案是三条边权值之和。......
  • 2023ICLR_Embedding fourier for ultra-high-definition Low-light image enhancement
    1. #narrow切片x1,x2=(x.narrow(1,0,self.split_len1),x.narrow(1,self.split_len1,self.split_len2))假设输入的张量是x,那么这句代码的作用是将x在第1维(即行数)上分别切割为两个长度分别为self.split_len1和self.split_len2的子张量,分别赋值给变量x1和x2。其中,narrow......
  • leetcode 342. Power of Four
    Givenaninteger(signed32bits),writeafunctiontocheckwhetheritisapowerof4.Example:Givennum=16,returntrue.Givennum=5,returnfalse.Followup:Couldyousolveitwithoutloops/recursion?解法1,经典的数学解法:classSolution(object):def......
  • Fourier级数
    Fourier在研究热传导的问题时,用\(\dfrac{a_0}{2}+\sum\limits_{n=1}^{\infty}(a_n\cosnx+b_n\sinnx)\)的形式来表示一个周期为\(2\pi\)的函数\(f(x)\),取得了很成功的结果。于是他开始猜测任何以\(2\pi\)为周期的函数都可以用这种形式,这种三角函数的无穷求和的形式,来表示。这个......
  • FourCastNet
    先写自适应傅里叶神经算子(AFNO)AFNO这篇文章的标题和摘要前几句定调了一个基调,就是说AFNO这个东西提出来,是为了替换transformer里面的多头自注意力,作为一个更高效的tokenmixer出现摘要:1.AFNO是基于运算符学习的原则性基础,它使我们能够将令牌混合作为一个连续的全局卷积,而不依......