首页 > 其他分享 >CF166D 题解

CF166D 题解

时间:2024-06-20 17:33:40浏览次数:11  
标签:le 匹配 int 题解 cin CF166D 鞋子

看到其它题解代码颇长,蒟蒻在此贡献一个二分图最大匹配的解法。

题意

鞋店里有 \(n\) ( \(1 \le n \le 10^5\) ) 双鞋子,第 \(i\) 双鞋子有价格 \(c_i\) 与尺码 \(s_i\) ( \(1 \le c_i, s_i \le 10^9\) ),保证 \(s_i\) 互不相同。

有 \(m\) ( \(1 \le m \le 10^5\) ) 位顾客光临,第 \(i\) 位顾客有 \(d_i\) ( \(1 \le d_i \le 10^9\) ) 元钱,他可以穿尺码为 \(l_i\) 或者 \(l_i + 1\) 的鞋子。

求出一种将鞋子卖给顾客的方法,使得获利最大,输出方案。

题解

观察到题目相当于将顾客与鞋子进行匹配,因为 \(s_i\) 互不相同,所以每个顾客最多可以匹配两个鞋子。问题转化为:有一个二分图,左右分别有 \(n, m\) 个点,左边的点有点权,右边的每个点的度数不超过 \(2\),求最大带权匹配。

注意到右边每个点度数不大于 \(2\),这保证了可以用匈牙利算法跑二分图最大带权匹配,若 \(n, m\) 同阶那么复杂度是 \(O(n)\) 的。

我们贪心地将左边的点按点权从大到小排序,然后依次匹配,要求每次匹配不能挤掉已经匹配的点,这样答案一定是最大的。

代码非常好写:

#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define per(i, r, l) for (int i = r; i >= l; --i)
using namespace std;
using i64 = long long;
const int N = 1E5 + 5;
int n, m, L[N], vis[N], ans;
i64 Ans;
map<int, int> mp;
vector<int> adj[N];
struct shoe {int c, s, id;} a[N];
bool cmp(shoe a, shoe b) {return a.c > b.c;}
bool match(int x, int f) {
    if (vis[x] == f) return 0; vis[x] = f;
    for (auto v : adj[x]) {
        if (!L[v] || match(L[v], f)) return L[v] = x, 1;
    } return 0;
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(nullptr);
    cin >> n;
    rep(i, 1, n) cin >> a[i].c >> a[i].s, a[i].id = i;
    sort(a + 1, a + 1 + n, cmp);
    rep(i, 1, n) mp[a[i].s] = i;
    cin >> m;
    rep(i, 1, m) {
        int d, l; cin >> d >> l;
        auto check = [&](int k) {
            if (mp.count(k) && a[mp[k]].c <= d)
                adj[mp[k]].push_back(i);
        } ;
        check(l); check(l + 1);
    }
    rep(i, 1, n) if (match(i, i)) ++ans, Ans += a[i].c;
    cout << Ans << '\n' << ans << '\n';
    rep(i, 1, m) if (L[i]) cout << i << ' ' << a[L[i]].id << '\n';
}

标签:le,匹配,int,题解,cin,CF166D,鞋子
From: https://www.cnblogs.com/CTHOOH/p/18259093

相关文章

  • SOLIDWORKS常见使用问题解决方案 慧德敏学
    本文Solidkits为大家分享SOLIDWORKS常见使用问题解决方案,让我们一起学习,使设计工作效率更高。1、如何隐藏装配体里头的零件?—右键点击零件或者树状图中的零件名字,然后点眼睛那个图标。更快捷的方式,只需要把鼠标放到那个零件上,按一下Tab,隐藏了。2、如何恢复隐藏装配体里头的零......
  • CF988D Points and Powers of Two 题解
    题目传送门题目大意题目描述在坐标线上有nnn个不同的点,第iii......
  • CF212D 题解
    根据此题首次学到二阶差分Trick,好题。题意给出一个序列\(\{a_n\}\),满足\(n\le10^6,1\lea_i\le10^9\),定义函数\(f(i,k)\)为:\[f(i,k)=\min\limits_{j=i}^{i+k-1}a_j\]你需要回答\(m\)个询问,每次询问给出一个整数\(k\)(\(1\lek\len\)),求所有\(f(i,k......
  • DataTrigger 数据触发器触发动画的方式及问题解决
    在WPF中通过触发器实现动画的方式很常见,这里记录一下再使用DataTrigger数据触发器触发动画的一些经验,以便备忘。一、数据触发器DataTrigger与普通的触发器Trigger区别:Trigger普通触发器<!--样式--><StyleTargetType="TextBlock"><Style.Triggers><!--这里......
  • 2024年BCSP-X初赛真题解析(小高组)
    学习C++从娃娃抓起!学习下帝都的对标CSP的BCSP考试,记录下CSP-J备考学习的每一个瞬间。单选题第1题计算机在工作过程中突然停电,()中的信息不会丢失。A.显存B.寄存器C.RAMD.ROM【答案】:D第2题中缀表达式a*(b+c)-d的后缀形式是()。A.abcd*±B.abc+*d-C.abc*+d-D.-+......
  • P6261 [ICPC2019 WF] Traffic Blights 题解
    思路考虑题目要求的是什么。假设\(p_i\)代表通过前\(i\)个红绿灯的概率。那么我们的答案即为\(p_i-p_{i-1}\)。不妨设\(w_i=r_i+g_i\)。我们的限制条件类似:\[t\not\equiva_i\pmodw_i\]那么所有红绿灯会形成周期\(lcm(w_1,w_2,\cdots,w_n)\)。由于\(2019!\)肯......
  • P10540 [THUPC2024] 古明地枣的袜子 题解
    题意:一个长为\(n\)的序列\(a\),初始全为零。\(n\)个操作,第\(i\)个操作形如给\(a_1,\cdots,a_{x_i}\)加上\(y_i\)。\(m\)次查询,给定\(l,r\),求对\(a\)执行第\(l\simr\)个操作后数列\(a\)的全局最大值。\(1\len,m\le5\cdot10^5,1\lex_i,|y_i|\len,1\lel\ler\len\),时间限......
  • GDCPC 2024 部分题解
    老年人过来对着会的题口胡几发B.腊肠披萨 题意翻译:给你n个小写字母串,求所有小写字母串两两之间的最长公共前缀的乘方和,对一个任意数取模。比较显然的,看到多串公共前缀直接建Trie统计贡献。建好之后对每个串在Trie上走,每走一步加上当前子树内串个数和父子树内串个数之差,就能......
  • LeetCode80. 删除有序数组中的重复项 II题解
    LeetCode80.删除有序数组中的重复项II题解题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/题目描述:给你一个有序数组nums,请你原地删除重复出现的元素,使得出现次数超过两次的元素只出现两次,返回删除后数组的新长度。不要使用额外的数......
  • LeetCode26. 删除有序数组中的重复项题解
    LeetCode26.删除有序数组中的重复项题解题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array题目描述:给你一个非严格递增排列的数组nums,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一......