因为是字典序所以贪心选当前能选的最小的,所以问题就在于怎么快速计算当前这个位置能不能选枚举的字母

重排之后的序列是可以和原序列完美匹配的,而完美匹配需要满足hall定理,也就是左边任意k个集合一定和右边至少k个点相连

又一共6个字符,原序列中相同字符点连出的点集是一样的,所以只要2^6个字符集合满足hall定理,每次这样枚举状压判断一下即可

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100005;
int n,m,sm[N],f[N][70],ok[N];
char s[N],c[10],flg,ans[N];
int main()
{
scanf("%s%d",s+1,&m);
n=strlen(s+1);
for(int i=1;i<=n;i++)
for(int j=0;j<(1<<6);j++)
if(j&(1<<(s[i]-'a')))
sm[j]++;
for(int i=1;i<=n;i++)
ok[i]=(1<<6)-1;
for(int i=1,x;i<=m;i++)
{
scanf("%d%s",&x,c+1);
ok[x]=0;
for(int j=1;j<=strlen(c+1);j++)
ok[x]+=(1<<(c[j]-'a'));
}
for(int i=n;i>=1;i--)
for(int j=0;j<(1<<6);j++)
f[i][j]=f[i+1][j]+(((j&ok[i])==ok[i])?1:0);
for(int i=1;i<=n;i++)
{
bool fl=0;
for(int j=0;j<6&&!fl;j++)
if(sm[1<<j]&&(ok[i]&(1<<j)))
{
flg=1;
for(int k=0;k<(1<<6)&&flg;k++)
if(f[i+1][k]>sm[k]-((k>>j)&1))
flg=0;
if(flg)
{
fl=1;
ans[i]='a'+j;
for(int k=0;k<(1<<6);k++)
if(k&(1<<j))
sm[k]--;
}
}
if(!flg)
{
puts("Impossible");
return 0;
}
}
for(int i=1;i<=n;i++)
printf("%c",ans[i]);
return 0;
}

最新文章

  1. 开发常用图标png、ico 图标下载
  2. 利用Java代码在某些时刻创建Spring上下文
  3. Win10 创建应用程序包及部署
  4. 通过PowerShell获取Windows系统密码Hash
  5. Lua开发环境搭建(Mac)
  6. HDU 5274 Dylans loves tree(树链剖分)
  7. ****Curling 2.0(深搜+回溯)
  8. 2016大连网络赛 Weak Pair
  9. windows利用iis配置反向代理实现ECS内网互通oss
  10. LINUX 笔记-crontab命令
  11. asp.net core中写入自定义中间件
  12. pycharm2019+破解补丁
  13. memcache 常用方法
  14. is not writable or has an invalid setter method错误的解决
  15. ConcurrentHashMap源码分析_JDK1.8版本
  16. 萌新程序媛的首个作品,基于NoSQL的内容管理及低码开发平台
  17. UVA 11136 Hoax or what (multiset)
  18. sublime快捷键功能记录
  19. MySQL 日常运维业务账号权限的控制
  20. C struct中的位域 bitfield

热门文章

  1. Java中Iterator的fast-fail分析
  2. wifi androd 整体框架
  3. BZOJ 4519 [CQOI2016]不同的最小割
  4. 20145239杜文超 《Java程序设计》第4周学习总结
  5. 版本名称SNAPSHOT、alpha、beta、release、GA含义
  6. Buffer的数据存取
  7. bootstrap.min.css.map
  8. python把源代码打包成.exe文件
  9. Go丨语言学习笔记--func
  10. skynet实践(9)-随机数重复问题