【2018 ccpc-final Gym 102055】B.Balance of the Force(枚举最大值)

https://codeforces.com/gym/102055/problem/B

题意

宇宙中有两个阵营,分别为光明和黑暗,现在有n个骑士,每个骑士都能选择加入黑暗或者光明的阵营,加入后的能力值分别为D和L,已知有m对骑士不愿意在同一个阵营,请问如何分配,能使得能力最高的骑士和能力最低的骑士之间的能力差值最小?

题解

对于差值尽量小的问题,可以采用枚举最大值,然后使得最小值尽量大。

此题关键点便是枚举最大值,找到最大的最小值,更新答案。

首先对骑士进行二分图判定,并把他们看成一个连通块,可以知道这个连通块里的最大值mx和最小值mn有两种方案(一部分在光明,一部分在黑暗,也可以反过来),记录下这两种方案。
将这些方案按照最大值从小到大排序。
从左到右依次枚举最大值 curmx
假设当前位置最大值为curmx,位置为i
如果[1,i-1]中的连通块个数等于二分图缩点判定后的个数,那么就可以找mn的最小值curmn。更新下答案 ans = min(ans, curmx-curmn)
但是有个地方要注意,可能得出的curmn是当前方案i的孪生方案中的mn(每个块会有两种方案),因为每个连通块只能选一个方案,所以必须把前面这个孪生方案的mx的贡献给去掉。这样求出来的curmn就是正确的。
枚举完这个i后,应该更新当前位置的mn,同时如果前面有孪生方案j的话,那么两个位置都需要更新一下,更新的值便是max(a[j].mn, a[i].mn)。因为要让最小值尽量大。
上述的步骤可以用数据结构在logn时间内完成。
总复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

代码

#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2e5+5;
const int INF = 0x3f3f3f3f;
vector<int> G[maxn];
int color[maxn], n, m, val[maxn][2], sum[maxn];
int _mn[maxn<<3], pos[maxn];
bool vis[maxn];

struct node {
   
	int mx,mn;
	int id;
	bool operator < (const node& rhs) const {
   
		return mx < rhs.mx;
	}
}a[maxn*2];

void pushup(int rt) {
   
	_mn[rt] = min(_mn[rt<<1], _mn[rt<<1|1]);
}
void build(int l,
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值