首页 > 其他分享 >Luogu6775 [NOI2020] 制作菜品 做题记录

Luogu6775 [NOI2020] 制作菜品 做题记录

时间:2024-07-25 09:51:10浏览次数:11  
标签:Luogu6775 ll len id1 NOI2020 菜品 define id lld

link

主要记录一下做题过程。

首先题目看上去很不好处理,考虑从部分分的角度入手。

先看 \(m=n-1\) 的部分分,这个性质让我们很容易想到一棵树。考虑把原材料当作点,菜品当作边,一道连接 \((x,y)\) 的菜品表示只能用编号为 \(x\) 和 \(y\) 的原材料。

对于这棵树,我们每次选择一个叶子,然后处理掉连接叶子的边表示的菜品,并删掉叶子。可以发现,一棵树确定了唯一一种方案。

但是这个方案不一定合法。当叶子原材料数量 \(> k\) 或一个点的原材料数量被减到负数时,方案不合法。

我们考虑归纳构造,不断将点数减小。一种很直接的想法是设 \(x,y\) 为 \(d\) 最大和最小的点,每次在 \(x,y\) 之间连一条边,然后保留 \(x\),更新 \(d_x\gets d_x + d_y - k\)。

这是否一定合法?

  • 由于 \(\sum\limits_{i = 1} ^ n d_i= mk = (n - 1)k\),得 \(\dfrac {\sum_{i = 1} ^ n d_i}n = \dfrac {n - 1}n k\),可知 \(\overline{d} < k\),那么一定有 \(d_y < k\)。

  • 考虑最坏情况下,除了 \(d_y\),其他点的 \(d_i\) 都和 \(d_x\) 相同,此时 \(\sum\limits_{i = 1} ^ n d_i = d_y + (n - 1) d_x = (n - 1)k\),可得 \(\dfrac {d_y}{n - 1} + d_x = k\),那么 \(d_x + d_y > k\)。

所以一定合法,这样我们就做完了 \(m = n - 1\) 的部分分。

考虑 \(m \ge n - 1\) 的部分分,很容易想到转化成 \(m = n - 1\) 的形式。考虑归纳构造,一个直接的想法是,每次选取 \(d_1,d_2,...,d_n\) 中最大的点 \(x\),然后直接 \(d_x\gets d_x - k\)。再次验证合法性:

  • 考虑此时 \(m\ge n\),且 \(\sum\limits_{i = 1} ^ n d_i = mk\ge nk\),则 \(\overline d \ge k\),显然有 \(d_x = \max d_i \ge k\)。

注意有个坑点,就是如果 \(d_x = k\),那么直接令 \(n\gets n - 1\) 并删掉 \(d_x\),官方数据没有卡,但是洛谷有 Hack 数据。

最后考虑 \(m = n - 2\) 的部分,边数竟然比树还少,此时这张图一定有至少两个连通块。可以发现,三个及以上个连通块一定不优,所以我们只需要枚举一个连通块。

此时这两个连通块都是树,如果找出了连通块,可以转成 \(m = n - 1\) 的形式。考虑一个连通块 \(S\) 的合法条件,为 \(\sum\limits_{i \in S} d_i = (|S| - 1)k\),这个显然可以背包解决。

可以把每个 \(d_i\) 减去 \(k\),就不用存 \(|S|\) 这一维,剩下直接 bitset 即可。注意此时 \(m\) 与 \(n\) 同级,时间复杂度 \(O(\dfrac {n^2k} \omega)\)。

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define pir pair <ll, ll>
#define mkp make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
const ll maxn = 510;
ll t, n, m, k, d[maxn], id1[maxn], id2[maxn], len1, len2;
bitset <5000005> f[maxn];
bool cmp(ll x, ll y) {return d[x] < d[y];}
void sort_insert(ll *id, ll len) {
	ll i, x = id[len];
	for(i = len - 1; i; i--)
		if(d[id[i]] <= d[x]) break;
	for(ll j = len; j > i + 1; j--) id[j] =  id[j - 1];
	id[i + 1] = x;
}
void solve(ll *id, ll len) {
	sort(id + 1, id + 1 + len, cmp);
	while(len > 1) {
		printf("%lld %lld %lld %lld\n", 
			   id[1], d[id[1]], id[len], k - d[id[1]]);
		d[id[len]] += d[id[1]] - k;
		for(ll i = 1; i < len; i++) id[i] = id[i + 1];
		--len, sort_insert(id, len);
	}
}
void scheme(ll i, ll j) {
	if(i == 0) return;
	ll x = d[i] - k;
	if(j - x >= 0 && f[i - 1][j - x]) {
		id1[++len1] = i;
		scheme(i - 1, j - x);
	} else {
		id2[++len2] = i;
		scheme(i - 1, j);
	}
}
int main() {
	scanf("%lld", &t);
	while(t--) {
		scanf("%lld%lld%lld", &n, &m, &k);
		for(ll i = 1; i <= n; i++) scanf("%lld", d + i);
		if(m == n - 2) {
			ll B = m * k;
			f[0].reset(), f[0][B] = 1;
			for(ll i = 1; i <= n; i++) {
				ll x = d[i] - k;
				if(x >= 0) f[i] = f[i - 1] | (f[i - 1] << x);
				else f[i] = f[i - 1] | (f[i - 1] >> (-x));
			}
			if(!f[n][B - k]) {
				puts("-1"); continue;
			} len1 = len2 = 0, scheme(n, B - k);
			solve(id1, len1);
			solve(id2, len2);
		} else {
			for(ll i = 1; i <= n; i++) id1[i] = i;
			sort(id1 + 1, id1 + 1 + n, cmp);
			for(ll i = m; n && i >= n; i--) {
				printf("%lld %lld\n", id1[n], k);
				d[id1[n]] -= k;
				if(d[id1[n]]) sort_insert(id1, n);
				else --n;
			}
			solve(id1, n);
		}
	}
	return 0;
}

标签:Luogu6775,ll,len,id1,NOI2020,菜品,define,id,lld
From: https://www.cnblogs.com/Sktn0089/p/18322365

相关文章

  • day03:菜品管理
    文章目录数据库设计公共字段填充问题分析实现思路代码演示新增菜品-文件上传介绍实现方式前端使用文件上传三要素使用阿里云OSS服务进行文件存储阿里云OSS使用服务进行文件上传新增菜品接口设计代码书写分页查询接口设计代码书写批量删除接口设计代码书写修改菜品......
  • 新增菜品——后端SpringBoot
    交互逻辑:页面发送ajax请求,请求服务端获取菜品分类数据并展示到下拉框中页面发送请求进行图片上传,请求服务端将图片保存到服务器页面发送请求进行图片下载,将上传的图片进行回显点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务器核心:    新增菜品功能,实......
  • 苍穹外卖笔记-06-菜品管理-菜品分类,公共字段填充
    菜品分类1菜品分类模块1.1需求分析与设计1.1.1产品原型1.1.2接口设计1.1.3表设计1.3代码实现1.4测试分类分页查询启用禁用分类修改分类信息新增菜品分类删除菜品分类2公共字段自动填充2.1问题分析2.2实现思路自定义注解AutoFill自定义切面AutoFillAspectMap......
  • 菜品分类模块删除接口+今天的图片不回显问题没有解决,明天再说。这篇随便写写吧,呕。+修
    点击删除按钮,删除菜品,也可以在左侧进行批量删除,故制定批量删除接口。删除规则如下 其中被套餐关联的菜品不能删除,因为删除这些菜品直接影响到套餐删除菜品后,关联的口味也要删除,所以这个删除蛮复杂的,并不是那种单表直接删的简单操作  请求参数和返回数据: 涉及到的表有......
  • 菜品条件分页查询
    这个不同于以往的那个条件分页查询,这个返回数据有个菜品表中没有的数据类型  反正这些Dto已经提供,乱用好吧,反正不需要我写。这个地方需要设计VO,因为菜品表中没有属性categoryName 我有个疑问,为啥这里还有个属性flavor,返回数据也没要求啊,这里来个DOTO,没关系继续写啊 ......
  • 菜品分类
    新增菜品  文件上传    springboot可以自动转换,不使用横线风格也算对思路:定义配置属性类读取yml中的配置项,然后把这个配置类注入到容器,这个对象就封装好了数据然后定义工具类AliossUtils,这个工具类的方法就是获取已上传图片在阿里云服务器中存储的url要使......
  • 菜品分类,做这个公共字段填充我真破防了
     第一个小节不属于业务功能开发,偏向技术的公共字段:在业务表中有很多相同的字段,例如创建人,创建时间,修改人,修改时间,在维护数据时候,都需给这些字段赋值,这样程序之中出现很多重复的代码  使用切面统一处理 枚举:可以标识当前操作的类型(insert或update)AOP:切面,统一拦截map......
  • 【SpringBoot3+Mybatis】小程序和后台管理系统 员工/分类/菜品/套餐管理 上传文件 CRU
    文章目录一、项目介绍&Github二、技术选型三、开发环境搭建四、员工管理4.1新增员工①sql②对象拷贝DTO与Entity③异常捕获与处理④动态获取当前登录者Id⑤ThreadLocal4.2员工分页查询①请求参数实体与响应数据实体②controller层③service层使用pageHelper......
  • 「题解」P6791 [SNOI2020] 取石子
    anti-game没有用,能取到\(n-1\)的必胜,不能取到\(n-1\)的必败,所以现在考虑取走最后石子获胜的情况。对于一个\(n\)来说合法的\(k\)一定是一个前缀,并且一定是贪心取最小的(留给对方的机会更小),所以启发将每个\(n\)最小的合法的\(k=a_n\)打出表来,找到最小的\(j\)满足\(......
  • [题解] P6773 [NOI2020] 命运
    P6773[NOI2020]命运给你一棵\(n\)个节点的树,要给每条边染成\(0\)或\(1\)。有\(m\)个限制\((u,v)\)满足\(u\)是\(v\)祖先,表示\(u\)到\(v\)的路径中至少有一条边被染成了1。求方案数。\(n,m\le5\times10^5\)。首先会想到容斥,但是很没前途,所以考虑......