首页 > 其他分享 >BZOJ4977 跳伞求生题解

BZOJ4977 跳伞求生题解

时间:2024-03-31 10:57:03浏览次数:23  
标签:BZOJ4977 费用 跳伞 增广 int 题解 队友 敌人 rightarrow

传送门

题意:有 \(n\) 个队友和 \(m\) 个敌人,每个队友 \(i\) 有 \(a_i\) 颗子弹。敌人 \(j\) 有 \(b_j\) 颗子弹。
队友击杀敌人,必须 \(a_i>b_j\),然后会获得 \(a_i-b_j+w_j\) 的收益。(\(w_j\): 每个敌人都有一个参数)
每个队友只能打一个敌人,可以不打。求最大收益。

【费用流模型】

上面那一排点表示队友,下面一排点表示敌人。若队友 \(a_i\) 能打敌人 \(b_j\),连边 \(a_i\rightarrow b_j\),容量 \(1\) 费用 \(0\)。

\(S\rightarrow a_i\),容量 \(1\) 费用 \(a_i\)。\(b_j\rightarrow T\),容量 \(1\) 费用 \(c_j=-b_j+w_j\)。注意这个费用可能是负数。

求最大费用任意流。

【模拟费用流】

任意流的题目一般都是用增量算法。

直接来不好弄,因为每个队友能杀什么敌人是随机的,我们还要遍历一遍。

可以观察一个性质:如果把队友和敌人都按子弹数量从小到大排序,每个队友打的都是一个前缀。

也就是这样:

考虑新增加点 \(a_n\)。

新的增广路有哪几种?

第一条增广路的收益是 \(a_n+c_k\),要求 \(c_k\rightarrow T\) 的边没用过。

第二条增广路的收益是 \(a_n+c_?\),要求 \(c_?\rightarrow T\) 的边没用过。

那这两种有什么区别呢?其实没有区别。较复杂的增广路只是让每个队友匹配的敌人变了。但是其实哪个队友匹配哪个敌人没有任何影响。

所以可以统合为:\(a_n+c_?\),要求 \(c_?\rightarrow T\) 没用过。

然后考虑环。

一种:

收益是 \(a_n-a_k\)。要求 \(S\rightarrow a_k\) 用过。

两种:

收益是 \(a_n+c_n-(a_k+c_k)\),因为是最大费用任意流,已经应用的增广路费用一定是正数,所以 \(a_k+c_k>0\),还不如直接应用增广路。

点击查看代码
#include <bits/stdc++.h>

using namespace std;
const int N = 1e5 + 5;
typedef long long ll;

int n, m;
ll a[N];
int pos[N]; //a[i]能打1~pos[i]

struct Enemy {
	ll b, w, c; 
} e[N];

bool cmp(Enemy a, Enemy b) {
	return a.b < b.b;
}

int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= m; i++) {
		cin >> e[i].b >> e[i].w;
		e[i].c = -e[i].b + e[i].w;
	}
	sort(a + 1, a + n + 1);
	sort(e + 1, e + m + 1, cmp);
	for (int i = 1, j = 0; i <= n; i++) {
		while (j + 1 <= m && e[j + 1].b < a[i])
			j++;
		pos[i] = j;
	}
	ll ans = 0;
	priority_queue<ll> q;
	priority_queue<ll, vector<ll>, greater<ll> > q2;
	for (int i = 1; i <= n; i++) {
		for (int j = pos[i - 1] + 1; j <= pos[i]; j++)
			q.push(e[j].c);
		ll tmp1 = -1, tmp2 = -1;
		if (!q.empty())
			tmp1 = a[i] + q.top();
		if (!q2.empty())
			tmp2 = a[i] - q2.top();
		if (tmp1 < 0 && tmp2 < 0)
			continue;
		if (tmp1 > tmp2) {
			ans += tmp1;
			q.pop();
			q2.push(a[i]);
		}
		else {
			ans += tmp2;
			q2.pop();
			q2.push(a[i]);
		}
	}
	cout << ans << endl;
	return 0;
}

标签:BZOJ4977,费用,跳伞,增广,int,题解,队友,敌人,rightarrow
From: https://www.cnblogs.com/FLY-lai/p/18106419

相关文章

  • 大学教材《C语言程序设计》(浙大版)课后习题解析 | 第七、八章
    概述    本文主要提供《C语言程序设计》(浙大版)第七、八章的课后习题解析,以方便同学们完成题目后作为参考对照。后续将更新第九、十章节的课后习题解析,如想了解更多,请持续关注该专栏。专栏直达链接:《C语言程序设计》(浙大版)_孟俊宇-MJY的博客-CSDN博客​http://t.cs......
  • 提问的力量:驱动问题解决、核心发现与创新启示
    目录问题解决的驱动力:提问的力量提问的力量:催生解决方案的火花提问的力量:启发新思想的源泉核心发现的推动力:提问的力量提问的力量:推动科学探索与发现提问的力量:揭示历史真相创新启示:提问的力量提问的力量:激发创新思维提问的力量:推动社会进步探索篇:提问与问题解决—......
  • 大学教材《C语言程序设计》(浙大版)课后习题解析 | 第五、六章
    概述   本文主要提供《C语言程序设计》(浙大版)第五、六章的课后习题解析,以方便同学们完成题目后作为参考对照。后续将更新第七、八章节课后习题解析,如想了解更多,请持续关注该专栏。专栏直达链接:《C语言程序设计》(浙大版)_孟俊宇-MJY的博客-CSDN博客http://t.csdnimg......
  • AT_abc347_e 题解
    很水。一个las数组,记录a[i]这个数上一次被加入是什么时候。注意,为防误判,在a[i]被删除的时候,将las[a[i]]设为\(0\)。你也可以这么理解:las是记录在哪出现的visit数组。每次加入一个数的时候,\(\left|S\right|\)就加\(1\),并且使las[a[i]]等于i。删除时,\(\left|S......
  • AT_abc347_c 题解
    最开始的思路爆炸了我就不写了。先d[i]%=(a+b)。然后,排序,破环为链,相当于存储了下一周。再然后,从\(1\)到\(n\)进行一个循环,若d[i+n-1]-d[i]+1<=a就输出Yes。它的原理是什么?翻译一下上面那个语句,就是“我前一个任务的日期的下一周距离我这个任务的日期小于等于节假日天......
  • ABC347题解
    省流:输+赢D按位分析。既然两个数异或后的结果是\(C\),那就考虑\(C\)中为\(1\)的数中有几个是在\(X\)当中的。假如\(\text{a-popcnt(X)==b-popcnt(Y)}\),那么在\(C\)中为\(0\)的数中随便选\(\text{a-popcnt(x)}\)个即可。注意longlong。codeE假如......
  • CF712E Memory and Casinos 题解
    假设只保留数组上\([l,r]\)的这段数,记\(f_i\)表示从点\(i\)出发到达\(n+1\)的概率,则有\(f_0=0,f_{n+1}=1,f_i=(1-p_i)f_{i-1}+p_if_{i+1}\),题目要求的是\(f_1\)。考虑对最后一个等式进行一些变换,把\(f_i\)的系数拆开得:\[p_if_i+(1-p_i)f_i=(1-p_i)f_{i-1}+p_if_{i+1......
  • ABC347G题解
    我不会,但是我会退火!第一眼,\(n\le20\)。退火,启动!大致思路就是随机选一个初始为0的数置为\(1\sim5\)中的某个数,显然图中没有0一定不比有0劣(把所有0改成同一个数一定不劣)。然后把单次计算的复杂度从\(O(n^2)\)变成\(O(1)\):更新有变化位置的值就行了。瞎调调参数......
  • P5624 [Celeste-A] Black Moonrise 题解
    考虑莫队。记数\(i\)的个数为\(c_i\),套路地用莫比乌斯函数容斥,发现答案为\(\sum_{i=1}^{10^5}\frac{c_i(c_i+1)}2\sum_{d|i}\mu(\fracid)d\)。先预处理出前面的常数和每个数的因子,每次移动端点枚举因子更新答案即可。因为数是随机的,所以时间复杂度\(\mathcalO(n\sqrtn......
  • 信息工程大学第五届超越杯程序设计竞赛(同步赛)题解
    比赛传送门c++模板框架#pragmaGCCoptimize(3,"Ofast","inline")#include<bits/stdc++.h>#definerep(i,a,b)for(inti=a;i<b;++i)#defineper(i,a,b)for(inti=a;i>b;--i)#definesesecond#definefifirst#defineendl'\n�......