zoukankan      html  css  js  c++  java
  • CF1009G Allowed Letters

    link

    题意:

    给你一个长为n的串,字符集'a'~'f'。你可以重排这个串,满足指定m个位置上只能放特定的字符,m个位置以及字符集会给出。求字典序最小的串?

    $n,mleq 10^5.$

    题解:

    稍微需要那么一点技巧的贪心。

    贪心策略比较显然,无非就是从左往右放尽可能小的字符,同时保证当前位置之后有合法解。

    考虑预处理a[i]:i位置可以放的字符集;cnt[i]:集合i的字符在整个串中出现的次数;b[i][j]:i~n位置中a[]被集合j包含的个数。每次判断一个字符是否可行,只要枚举任意一个集合j,如果j集合中所有可用的字符在之后每个放一个位置还不够的话,说明不合法。

    依次贪心下去即可。

    复杂度$mathcal{O}(6 imes 2^6 imes n)$。

    code:

     1 #include<bits/stdc++.h>
     2 #define rep(i,x,y) for (int i=(x);i<=(y);i++)
     3 #define per(i,x,y) for (int i=(x);i>=(y);i--)
     4 #define ll long long
     5 #define inf 1000000001
     6 #define y1 y1___
     7 using namespace std;
     8 ll read(){
     9     char ch=getchar();ll x=0;int op=1;
    10     for (;!isdigit(ch);ch=getchar()) if (ch=='-') op=-1;
    11     for (;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    12     return x*op;
    13 }
    14 #define N 100005
    15 #define M 70
    16 int n,m,a[N],b[N][M],tmp[M],cnt[M];char s[N],s2[N],ans[N];
    17 int main(){
    18     scanf("%s",s+1);n=strlen(s+1);
    19     m=read();
    20     while (m--){
    21         int k=read(),l;scanf("%s",s2+1);l=strlen(s2+1);
    22         rep (i,1,l) a[k]|=1<<s2[i]-'a';//该位置可以放的字符集
    23     }
    24     rep (i,1,n) if (!a[i]) a[i]=(1<<6)-1;
    25     rep (i,1,n){
    26         int x=s[i]-'a';
    27         rep (j,0,(1<<6)-1) if (j>>x&1) cnt[j]++;//cnt[i]:集合i的字符在整个串中出现的次数
    28     }
    29     per (i,n,1) rep (j,0,(1<<6)-1){//b[i][j]:i~n位置中a[]被集合j包含的个数
    30         if ((j&a[i])==a[i]) tmp[j]++;
    31         b[i][j]=tmp[j];
    32     }
    33     rep (p,1,n-1){
    34         bool flag=0;
    35         rep (i,0,5) if (cnt[1<<i]&&(a[p]>>i&1)){//贪心,保证之后还能放
    36             bool chk=1;
    37             rep (j,0,(1<<6)-1) if (cnt[j]-(j>>i&1)<b[p+1][j]){//j集合中每个字符放一个位置还不够,不合法
    38                 chk=0;
    39                 break;
    40             }
    41             if (chk){
    42                 flag=1;ans[p]=i+'a';
    43                 rep (j,0,(1<<6)-1) if (j>>i&1) cnt[j]--;
    44             }
    45         }
    46         if (!flag){puts("Impossible");exit(0);}
    47     }
    48     bool flag=0;
    49     rep (i,0,5) if (cnt[1<<i]&&(a[n]>>i&1)){
    50         flag=1;ans[n]=i+'a';
    51         break;
    52     }
    53     if (!flag){puts("Impossible");exit(0);}
    54     ans[n+1]='';
    55     puts(ans+1);
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    centos7安装pcntl扩展
    MySQL_数据库命名规范及约定
    tp5命名规范
    PHP易混淆函数的区别及用法汇总(函数和方法的区别)
    Mysql密码安全策略修改
    linux mysql 允许进行远程连接 比如 navicat
    解决 docker run 报错 oci runtime error
    如何删除Git中缓存的用户名和密码
    PHP heredoc 用法
    python日志模块
  • 原文地址:https://www.cnblogs.com/bestFy/p/9313500.html
Copyright © 2011-2022 走看看