题意

给你一个长为 \(n\) 的串,字符集为 \(a,b,c,d,e,f\) 。你可以将整个串打乱之后重新放置,但是某些位置上有一些限制:必须放某个字符集的字符。问字典序最小的串,如果无解输出 "Impossible"。

\(n\le 10^5\)

分析

  • 每次贪心地选择字典序最小的字符判断,判断后面是否可以完美匹配。可以考虑霍尔定理。

  • 这里有两种想法,一种是对于每种字符开一个 \(bitset​\) 记录被包含的位置然后求并集(字符匹配位置);另一种则是考虑 "非完美算法" : 枚举一个字符集作为某些位置的字符集的并集,然后将所有可选字符集被完全包含的位置数量作为答案(位置匹配字符)。

  • 容易发现第二种做法虽然可能求单个答案并不准确,但一定能够保证最终的答案是正确的,因为如果我们枚举的并集比实际那些位置字符集的并集要大的话,会更容易满足 $|X|\le |\digamma(X)| $ ,一定不会比实际的并集影响大。

  • 因为要递推,所以考虑第二种方式。令 \(cnt(i)(S)\) 表示以 \(i\) 结尾的后缀中,字符集是 \(S\) 的子集的位置个数,如果有完美匹配则需要满足对于任意的 \(S\) 有: \(\sum\limits_{c\in S}num(c)\ge cnt(i+1)(S)\) ,其中 \(num(c)\) 表示剩余 \(c\) 字符的个数。

  • 总时间复杂度为 \(O(6n\times 2^6)\)。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define pb push_back
#define re(x) memset(x, 0, sizeof x)
inline int gi() {
int x = 0,f = 1;
char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
return x * f;
}
template <typename T> inline void Max(T &a, T b){if(a < b) a = b;}
template <typename T> inline void Min(T &a, T b){if(a > b) a = b;}
const int N = 1e5 + 7;
int n, m;
int cnt[N][1 << 6], val[N], num[6], ans[N];
char s[N], s2[N];
int main() {
scanf("%s", s + 1);
n = strlen(s + 1);
rep(i, 1, n) num[s[i] - 'a'] ++;
m = gi();
rep(i, 1, m) {
int x = gi();
scanf("%s", s2 + 1);
int len = strlen(s2 + 1);
rep(j, 1, len) val[x] |= (1 << s2[j] - 'a');
}
for(int i = n; i; --i) {
if(!val[i]) val[i] = (1 << 6) - 1;
for(int j = 0; j < 1 << 6; ++j) {
cnt[i][j] = cnt[i + 1][j];
if((j & val[i]) == val[i]) cnt[i][j] ++;
}
}
rep(i, 1, n) {
for(int j = 0; j < 6; ++j) if(cnt[j] && val[i] >> j & 1){
num[j]--;bool fg = 1;
for(int S = 0; S < 1 << 6; ++S) {
int c = 0;
for(int k = 0; k < 6; ++k) if(S >> k & 1) c += num[k];
if(c < cnt[i + 1][S]) fg = 0;
}
if(fg) {ans[i] = j; goto A;}
num[j]++;
}
return puts("Impossible"), 0;
A:;
}
rep(i, 1, n) printf("%c", ans[i] + 'a');
puts("");
return 0;
}

[CF1009G]Allowed Letters[贪心+霍尔定理]的更多相关文章

  1. CF1009G Allowed Letters

    link 题意: 给你一个长为n的串,字符集'a'~'f'.你可以重排这个串,满足指定m个位置上只能放特定的字符,m个位置以及字符集会给出.求字典序最小的串? $n,m\leq 10^5.$ 题解: ...

  2. Codeforces 1009G Allowed Letters FMT,二分图,二分图匹配,霍尔定理

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF1009G.html 题目传送门 - CF1009G 题意 给定一个长度为 $n$ 的字符串 $s$ .并给定 ...

  3. Codeforces 1009G Allowed Letters 最大流转最小割 sosdp

    Allowed Letters 最直观的想法是贪心取, 然后网络流取check可不可行, 然后T了. 想到最大流可以等于最小割, 那么我们状压枚举字符代表的6个点连向汇点是否断掉, 然后再枚举64个本 ...

  4. 【题解】 AtCoder ARC 076 F - Exhausted? (霍尔定理+线段树)

    题面 题目大意: 给你\(m\)张椅子,排成一行,告诉你\(n\)个人,每个人可以坐的座位为\([1,l]\bigcup[r,m]\),为了让所有人坐下,问至少还要加多少张椅子. Solution: ...

  5. 【题解】 bzoj1135: [POI2009]Lyz (线段树+霍尔定理)

    题面戳我 Solution 二分图是显然的,用二分图匹配显然在这个范围会炸的很惨,我们考虑用霍尔定理. 我们任意选取穿\(l,r\)的号码鞋子的人,那么这些人可以穿的鞋子的范围是\(l,r+d\),这 ...

  6. 【题解】 bzoj3693: 圆桌会议 (线段树+霍尔定理)

    bzoj3693 Solution: 显然我们可以把人和位置抽象成点,就成了一个二分图,然后就可以用霍尔定理判断是否能有解 一开始我随便YY了一个\(check\)的方法:就是每次向后一组,我们就把那 ...

  7. [hdu5503]EarthCup[霍尔定理]

    题意 一共 \(n\) 只球队,两两之间会进行一场比赛,赢得一分输不得分,给出每只球队最后的得分,问能否构造每场比赛的输赢情况使得得分成立.多组数据 \(T\le 10,n\le 5\times 10 ...

  8. [CF981F]Round Marriage[二分+霍尔定理]

    题意 洛谷 分析 参考了Icefox 首先二分,然后考虑霍尔定理判断是否有完美匹配.如果是序列的话,因为这里不会出现 \(j<i,L(i)<L(j)\) 或者 \(j<i,R(i)& ...

  9. [BZOJ3693]圆桌会议[霍尔定理+线段树]

    题意 题目链接 分析 又是一个二分图匹配的问题,考虑霍尔定理. 根据套路我们知道只需要检查 "区间的并是一段连续的区间" 这些子集. 首先将环倍长.考虑枚举答案的区间并的右端点 \ ...

随机推荐

  1. 插入图片新方式:data:image

    我们在使用<img>标签和给元素添加背景图片时,不一定要使用外部的图片地址,也可以直接把图片数据定义在页面上.对于一些“小”的数据,可以在网页中直接嵌入,而不是从外部文件载入. 如何使用 ...

  2. 动态修改css文件中,具体的class中的个别属性值。

    function setStyleSheetObjCssClassProperty(pStyleSheetObj, pSelectorText, pProperty, pValue) { var pS ...

  3. pycrypto加解密

    下载pycrypto:http://www.voidspace.org.uk/python/modules.shtml#pycrypto (Windows版本) from Crypto.Cipher ...

  4. cat > file << EOF 与 cat > file << -

    当我们在使用kickstart 的时候,会遇到写网卡配置文件的情况,这时候我们使用cat > file << EOF 命令等,可以从标准输入中接受输入并保存到 file 文件中. c ...

  5. orcl创建表及管理表

    常用的字段数据类型: .字符串(varchar2(n)) n表示保存最大长度,基本200作用..整数(number(n)) n位的整数,也可用int代替.小数(number(n,m)) m为小数位,n ...

  6. Spark 分布式调试工具

    0. 说明 编写工具类,考察 Spark 分布式程序的执行地点 1. 工具类编写 [ JMX ] Java Management Extend , Java 管理扩展服务. 主要用于运维和监控. [测 ...

  7. 利用MSF的MS08_067模块攻击windows server 2003 SP2中文版系统

    一.测试环境 攻击机:kali(NMAP+MSF) 靶机:windows server 2003 SP2 中文版 利用漏洞:MS08_067 二.漏洞描述 MS08-067漏洞的全称为“Windows ...

  8. CSS 居中大全(转)

    引用:http://jinlong.github.io/blog/2013/08/13/centering-all-the-directions/ CSS 居中大全 AUG 13TH, 2013 |  ...

  9. 用JS制作《飞机大作战》游戏_第3讲(玩家发射子弹)-陈远波

    一.公布上一讲中玩家飞机上.下.右移动实现的代码: /*=========================键盘按下事件 keycode为得到键盘相应键对应的数字==================== ...

  10. Mac上编译OpenJDK过程记录

    编译OpenJDK主要为了学习HotSpot,编译过程在很多相关书籍中都有所涉及,但由于机型.机子具体环境的不同,很难有资料能够一步到位.还是得碰到具体问题通过上网查来一个个解决. 下载OpenJDK ...