JZOJ4336. 【WC2016模拟】rabbit

JZOJ4336. 【WC2016模拟】rabbit

题目描述:
在这里插入图片描述
在这里插入图片描述

这道题 10 p t s 10pts 的暴力就不说了。

对于 30 p t s 30pts 的部分分,写个网络流就可以过了。

对于 50 p t s 50pts 的部分分,可以贪心的对 b b 从大到小排序,然后每次前 a i a_{i} 个数减一,注意要维护单调性,多维护区间最大值最小值可以解决(目的是找到-1后不单调的地方,把操作后移,因为保证前面单调,后面单调,所以都单调。。。

正解很巧妙。首先基于 30 p t s 30pts 的网络流
在这里插入图片描述
根据最大流最小割定理,最大流等于最小割。
我们考虑左边 S S 连出的边的条数为 x x ,右边连向 T T 的边数为 y y S a Sa 为左边删去的边的总权值, S b Sb 同理。如果使图不连通,那么重边要删去 ( m x ) ( n y ) (m-x)(n-y) 条边。

所以总的价值就是 S a + S b + ( m x ) ( n y ) Sa+Sb+(m-x)(n-y)
首先贪心的将 a , b a,b 从小到大排序,保证 S a S b SaSb 最小。枚举 x x ,已知 m m n n x x ,我们的目的是使 S b ( m x ) y Sb-(m-x)y 最小。
f ( y ) = S b ( m x ) y f(y)=Sb-(m-x)y ,易知 f ( y ) f ( y 1 ) = b y ( m x ) f(y)-f(y-1)=b_{y}-(m-x) 。因为前面保证 b b 单调递增,所以差值单调递增。
不难看出 f f 长这样:
在这里插入图片描述
也就是求当 b y ( m x ) < = 0 b_{y}-(m-x)<=0 时最大的 y y
可以双指针。

这道题用桶排做到 O ( n ) O(n) ,但是因为我懒,直接用了 s o r t sort ,所以多了一只 l o g log

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 2500010;

long long n,m,a[N],b[N],suma[N],sumb[N],r,x,y;
long long ans = 0x3f3f3f3f3f3f3f3f;

int main()
{
	scanf("%lld%lld%lld%lld%lld%lld",&m,&n,&a[1],&x,&b[1],&y), r = n;
	for(int i = 1;i < m; ++ i) a[i + 1] = (a[i] * 58 + x) % (n + 1);
	for(int i = 1;i < n; ++ i) b[i + 1] = (b[i] * 58 + y) % (m + 1);
	sort(a + 1,a + 1 + m), sort(b + 1,b + 1 + n);
	
	for(int i = 1;i <= m; ++ i) suma[i] = suma[i - 1] + a[i];
	for(int i = 1;i <= n; ++ i) sumb[i] = sumb[i - 1] + b[i];
	
	for(int i = 0;i <= m; ++ i)
	{
		for(int j = r;j >= 0; -- j)
			if(b[j] <= (m - i)) { r = j; break; }
		ans = min(ans,suma[i] + sumb[r] + (m - i) * (n - r));
	}
	
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/INnovate2030/article/details/107850142