题意略。

思路:

首先是贪心, 我们从前往后依次从小到大考虑放哪个字符, 重点是判断放了这个字符后, 对于剩下的后缀是否存在合法解。

考虑每个位置的允许放的字符集合只有2 ^ 6种, 我们预处理一个后缀和f[i][j], 表示i~n中被集合j包含的个数。

考虑第i个位置放了字符c后, 要使得f[i+1][j]都 <= 对应的剩下的个数才能是合法的。

这里涉及到一个霍尔定理:二部图G中的两部分顶点组成的集合分别为X, Y;

G中有一组无公共点的边,一端恰好为组成X的点的充分必要条件是:X中的任意k个点至少与Y中的k个点相邻。

由于是选择任意k个(1 <= k <= |x|),所以我们需要考虑的是极端情况,如果极端情况满足了,那么剩余的情况也会被满足。

现在假设我们在当前位置填上了某个字符,我们最关心的是剩下能否合法,也就是剩下的位置能否被剩余字符填满。

其实所有的位置可以分为2 ^ 6 = 64种,如果我们选择的k个来自不同的种类,也就会给我们带来更多可以填入这k个位子的字符。

我所说的极端情况就是尽量减少可以填入这k个位子的字符,扩大我的k个位子。如果这种情况可以被满足,那么其他情况自然也就满足了。

开始我认为选择来自同一种的位子就是最极端的,其实这仅仅做到了字符数最小,没有做到位子最多。

比如我选择了状态为j的位子,我可以选择j的子集来扩大我的k,而且这不会给字符数带来任何增益。

详见代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn1 = 1e5 + ;
const int maxn2 = (<<); int f[maxn1][maxn2],mask[maxn1],cnt[maxn2],m;
char str[maxn1],tmp[],ans[maxn1]; int main(){
scanf("%s%d",str,&m);
int len = strlen(str);
if(m == ){
sort(str,str + len);
printf("%s\n",str);
return ;
}
for(int i = ;i < len;++i){
for(int j = ;j < maxn2;++j){
if(j & (<<(str[i] - 'a'))) ++cnt[j];
}
}
for(int i = ;i <= len;++i) mask[i] = maxn2 - ;
int pos;
for(int i = ;i < m;++i){
scanf("%d%s",&pos,tmp);
int l = strlen(tmp);
mask[pos] = ;
for(int j = ;j < l;++j)
mask[pos] += (<<(tmp[j] - 'a'));
}
for(int i = len;i >= ;--i){
for(int j = ;j < maxn2;++j){
f[i][j] = f[i + ][j];
if((mask[i] & j) == mask[i]) f[i][j] += ;
}
}
for(int i = ;i <= len;++i){
bool finish = false;
for(int j = ;j < ;++j){
if((mask[i] & (<<j)) == || !cnt[<<j]) continue;
bool ok = true;
for(int k = ;k < maxn2 && ok;++k){
if(f[i + ][k] > cnt[k] - ((k>>j) & )){
ok = false;
}
}
if(ok){
for(int k = ;k < maxn2;++k)
if((k>>j) & ) cnt[k] -= ;
ans[i] = 'a' + j;
finish = true;
break;
}
}
if(!finish){
printf("Impossible\n");
return ;
}
}
for(int i = ;i <= len;++i) printf("%c",ans[i]);
printf("\n");
return ;
}

Codeforces 1009G的更多相关文章

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

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

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

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

  3. Allowed Letters CodeForces - 1009G(状压思维)

    题意: 给出一个字符串 给出几个定点必须是哪个字母(或者是几个字母中的一个)  然后求在满足所有定点后的最小字符串 解析: 没错 这题是暴力 用状压暴力 “a - f” 用”0 - 5“ 这几个数字代 ...

  4. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  5. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  6. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  7. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  8. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  9. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

随机推荐

  1. 二十、Sql Server 保留几位小数的两种做法

    问题: 数据库里的 float momey 类型,都会精确到多位小数.但有时候 我们不需要那么精确,例如,只精确到两位有效数字. 解决: 1. 使用 Round() 函数,如 Round(@num,2 ...

  2. linux初学者-DNS配置篇

    linux初学者-DNS配置篇 DNS在之前的网络管理篇已经做过介绍,下文将叙述DNS在学习工作中的一些配置以及应用. 1.高速缓存DNS 一台主机通过DNS服务器询问域名解析IP是需要一定的时间的, ...

  3. bug探索常识

    1.什么是Bug探索测试? 探索测试是将测试设计和测试执行整合在一起,形成的一种测试方法. 2.探索性测试怎么做? 需要认真思考和分析结果,并且在探索测试的过程中做记录. 3.探索性测试的好处? 可以 ...

  4. DVWA-SQL注入

    SQL注入解题思路 寻找注入点,可以通过web扫描工具实现 通过注入点,尝试得到连接数据库的用户名,数据库名称,权限等信息. 猜解关键数据库表极其重要字段与内容. 通过获得的用户信息寻找后台进行登录. ...

  5. PID算法资料【视频+PDF介绍】

    最近一直有网友看到我的博客后,加我好友,问我能不能给发一些PID的资料,今天找了一些资料放到百度网盘上,给大家下载: 视频资料 链接:https://pan.baidu.com/s/12_IlLgBI ...

  6. Docker入门学习笔记

    Docker 什么是Docker 虚拟化技术 在计算机中,虚拟化是一种资源管理技术,将计算机中的各种实体资源如:CPU.硬盘.内存等予以抽象.转换后呈现出来打破实体结构间的不可切割的障碍,使用户可以比 ...

  7. WPF 打开网页

    1.利用浏览器打开using System.Diagnostics; Process proc = new System.Diagnostics.Process(); proc.StartInfo.F ...

  8. 为什么unsigned (-1)表示无符号整数的最大值

    整数在计算机中的表示 在计算机中,整数采用补码表示.当前主流编译器中整型在内存中占用四个字节,共32位. 机器数:一个数在计算机中的二进制表示形式, 叫做这个数的机器数.机器数是带符号的,在计算机用一 ...

  9. java并发编程(二)----创建并运行java线程

    实现线程的两种方式 上一节我们了解了关于线程的一些基本知识,下面我们正式进入多线程的实现环节.实现线程常用的有两种方式,一种是继承Thread类,一种是实现Runnable接口.当然还有第三种方式,那 ...

  10. java并发编程(十五)----(线程池)java线程池简介

    好的软件设计不建议手动创建和销毁线程.线程的创建和销毁是非常耗 CPU 和内存的,因为这需要 JVM 和操作系统的参与.64位 JVM 默认线程栈是大小1 MB.这就是为什么说在请求频繁时为每个小的请 ...