首页 > 其他分享 >CF1139E Maximize Mex 题解

CF1139E Maximize Mex 题解

时间:2023-05-25 22:01:08浏览次数:42  
标签:选人 CF1139E int 题解 long 能力 Maximize 社团 define

Description

\(n\) 个学生, \(m\) 个社团。每个学生有一个能力值,且仅属于一个社团。这 \(d\) 天内,每天从 \(m\) 个社团中选人,使得选出的人的能力值的 \(\text{mex}\) 最大。每天会有一个人在选人之前退团。

\(d,m \leq n \leq 5000\)

Solution

巧妙建图题。

  • 首先,我们可以很显然的知道要想使得 \(\text{mex}\) 值最大,我们应该贪心地先选能力值小的人,直到有一个能力值不能被表示。

  • 再次,我们考虑一个社团只能选一个人进行匹配、一个人和一个能力值相对应。于是我们可以将这个题抽象成一个二分图的问题:将能力值当成左部点,团体当成右部点。将一个社团里每个人的能力值和这个社团连边,跑最大图匹配即可。

  • 到了这一步,我们发现这么做的复杂度是 \(O(nmd)\) 的,不足以解决此题,需要进一步优化。我们发现,多一个人的情况肯定不比少一个人的情况差,因此我们可以想出从最后一天倒序考虑,从人员退出转化成人员加入,这样以后枚举能力值的时候就不需要每次从 \(0\) 开始枚举了。时间复杂度降为 \(O(dm)\) ,可以通过。

需要注意的一些坑点:

(1):因为 \(0\) 也可能是答案,所以 \(match\) 数组每次要初始化成 \(-1\) 而非 \(0\) ;

(2):题目给出的是学生先离开社团校长再选人,所以倒过来的话就是先选人再把学生加入进去。

Code

#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define next nxt
#define re register
#define il inline
const int N = 5e4 + 5;
using namespace std;
int max(int x,int y){return x > y ? x : y;}
int min(int x,int y){return x < y ? x : y;}

int match[N],vis[N],k[N],use[N];
int n,m,d,ans;
stack <int> st;
struct Node{
	int p,c;
}a[N];
struct node{
	int u,v,next;
}edge[N<<1]; int head[N],num_edge;


il int read()
{
	int f=0,s=0;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) f |= (ch=='-');
	for(; isdigit(ch);ch=getchar()) s = (s<<1) + (s<<3) + (ch^48);
	return f ? -s : s;
}

il void add(int from,int to)
{
	edge[++num_edge] = (node){from,to,head[from]};
	head[from] = num_edge;
}

il bool dfs(int x)
{
	for(re int i=head[x];i;i=edge[i].next)
	{
		int y = edge[i].v;
		if(vis[y]) continue;
		vis[y] = 1;
		if(match[y] == -1 || dfs(match[y]))
		{
			match[y] = x;
			return true;
		}
	}
	return false;
}

il void Main(int id)
{
	memset(vis , 0 , sizeof vis);
	while(dfs(ans)) { ans++; memset(vis , 0 , sizeof vis);}
	st.push(ans);
	add(a[k[id]].p,a[k[id]].c);
}

signed main()
{
	memset(match , -1 , sizeof match);
	n = read() , m = read();
	for(re int i=1;i<=n;i++) a[i].p = read();
	for(re int i=1;i<=n;i++) a[i].c = read();
	d = read();
	for(re int i=1;i<=d;i++) k[i] = read() , use[k[i]] = 1;
	for(re int i=1;i<=n;i++) if(!use[i]) add(a[i].p,a[i].c);
	for(re int i=d;i>=1;i--) Main(i);
	while(!st.empty()) cout << st.top() << "\n" , st.pop();
	return 0;
}

此外,由于此题数据过水,直接正着来,经过一些常数优化也能过。代码在这,仅供参考。

标签:选人,CF1139E,int,题解,long,能力,Maximize,社团,define
From: https://www.cnblogs.com/bloodstalk/p/17433092.html

相关文章

  • P8081 [COCI2011-2012#4] ZIMA 题解
    题意给定一个长度为\(n\)的序列。当连续\(T\)天温度都小于\(0\)时,则称这\(T\)天为一个冰期,冰期来临之前的\(2T\)天都被标记为警示状态.特殊地,如果一个冰期最长,那么它的前\(3T\)天会被标记为警示状态。如果有多个冰期最长,选一个。思路模拟预处理出每个冰期的长......
  • AT2395 [ARC071C] TrBBnsformBBtion 题解
    题目大意有两个只包含\(A\)和\(B\)的字符串,给出两种操作A可以变为BB,B可以变为A;AAA可以消去,BBB也可以消去。思路找规律。这里我们以A为主,将B全部变为A。因为可以无限次操作,那么就代表如果两个字符串可以相等,那么他们就一定能够经过转化后变成同一个字......
  • CF714B Filya and Homework 题解
    题意给定一个长度为\(n\)的数组。我们可以给一些数加上一个\(x\),也可以减去一个\(x\),也可以不加也不减。问:是否存在一个数\(x\),使得这个数组里各个数都相等。思路一道思维题首先考虑,在这个数组中,相同的元素,我们一定是给它做相同的操作,否则一定不相等,根据这个思想,......
  • UVA1514 Piece it together 题解
    图论题还是在于建图题意给定一个长度为\(n\timesm\)的网格图,有的地方是白方块,有的是黑方块,有的啥也没用。给你如下四种\(L\)形方块,询问是否存在方法,让这些方块正好就是给出的图的形状。$L$形方块如下思路二分图首先我们要想,为什么需要二分图:若能拼成,那么就说......
  • SP15637 Mr Youngs Picture Permutations 题解
    题意给定一个最多有\(5\)排的一个队伍,每一个位置对应一个同学,给定总人数和第\(i\)排要站\(n_i\)个人。要求每行左边的同学身高要大于右边的,每列从上往下要从大到小。问:满足要求的一共有多少种方案。思路DP首先考虑,在这个题目中,有用的状态有每列最后的人的高度,每行......
  • P8584 探索未知 题解
    题意给你\(n\)个分数,每个分数后面跟着一个操作符\(op\),如果为\(1\)就是加上这个分数,是\(2\)就减去。初始时是\(0\),询问\(n\)次操作后最后的分数是多少,化成最简分数。特殊地,如果最后是个整数,直接以整数的形式输出。思路模拟考试的时候一看就想到了[NOIP2020]......
  • P8587 新的家乡 题解
    题意给定\(n\)个高度分别为\(h_i\)的柱子,两个柱子能合并成一个\(h_i+h_j\)的新柱子,每根柱子至多被使用一次。询问最多能建出多少根高度相同的柱子,并且最优答案下柱子的高度有多少种情况。\(1\leqn\leq10^6\),\(1\leqh_i\leq3\times10^3\)。思路爆搜!首先我们......
  • P8585 球状精灵的传说 题解
    很好的一个题题意给你\(n\)个三元组\((r_1,r_2,r_3)\),并定义\(ρ=\lfloor\frac{1}{4}min(r_1,r_2,r_3)^3\rfloor\)。两个三元组能合并当且仅当这两个三元组有至少两个值相同,即从\((x_1,y,z)\)和\((x_2,y,z)\)变为\((x_1+x_2,y,z)\)。\((x,y,z)\)的位置不固定......
  • Android 修改 android/hardware/interfaces 下HIDL接口编译报异常问题解决
    最近要增加hostapd的一个HIDL接口,修改android/hardware/interfaces/wifi/hostapd/1.2/IHostapd.hal文件后编译报错如下:ERROR:[email protected]::IHostapdhashashacaed0a159a521bd4964e0fb8117320849109d3eeaff6a08b4d2506156ce6987whichdoesnotmatch......
  • P2480 古代猪文 题解
    题意:求\[g^{\sum_{k\midn}{n\choosek}}\]对\(999911659\)取模。\(1\len,g\le10^9\)。思路:首先根据欧拉定理,题目转化为求\(\displaystyle\sum_{k\midn}{n\choosek}\)对\(999911658\)取模的值。模数为合数不是很好做,因式分解发现\(999911658=2\times3\times467......