• EZOJ #387字符串


    分析

    似乎ttl的模拟赛t3总是折半搜索?

    先把所有串转化为每个字母的0/1状态

    之后我们将所有字符串分为两半

    分别枚举状态

    我们发现只有左右两边的字母状态相等才能保证这个集合合法

    所以我们在搜左半边的时候每次加入一个pair

    表示异或值为x用了y个数

    搜完后先将它排序

    然后搜右边的时候每次lower_bound一下即可

    似乎ttl的数据比较强我的代码常数又很大,所以要开O2才能过/kk

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    #define pi pair<int,int>
    #define int long long
    pi a[(1<<20)+5];
    int ans,wh[110],n,m,sum[30],cnt1,mx;
    char s[11000];
    inline void dfs1(int p,int lim,int now,int tot){
        if(p>lim){
          a[++cnt1]=mp(now,tot);
          return;
        }
        dfs1(p+1,lim,now^wh[p],tot+1);
        dfs1(p+1,lim,now,tot);
        return;
    }
    inline void dfs2(int p,int lim,int now,int tot){
        if(p>lim){
          pi *le=lower_bound(a+1,a+cnt1+1,mp(now,-1ll));
          pi *ri=lower_bound(a+1,a+cnt1+1,mp(now+1,-1ll));
          ans+=(ri-le);
          ri--;
          if((ri->fi)==now)mx=max(mx,(ri->se)+tot);
          return;
        }
        dfs2(p+1,lim,now^wh[p],tot+1);
        dfs2(p+1,lim,now,tot);
        return;
    }
    signed main(){
        int i,j,k;
        scanf("%lld",&n);
        for(i=1;i<=n;i++){
          memset(sum,0,sizeof(sum));
          scanf("%s",s);
          m=strlen(s);
          for(j=0;j<m;j++)sum[s[j]-'a']^=1;
          for(j=0;j<26;j++)
            wh[i]|=((1<<j)*sum[j]);
        }
        dfs1(1,n/2,0,0);
        sort(a+1,a+cnt1+1);
        dfs2(n/2+1,n,0,0);
        printf("%lld %lld
    ",ans-1ll,mx);
        return 0;
    }
  • 相关阅读:
    Summary for sql join in Oracle DB
    Merge data into table in Oracle
    PLSQL存储过程传出大量异常错误信息
    oracle 11g plsql解析json数据示例
    识别'低效执行'的SQL语句
    如何开启MySQL 5.7.12 的二进制日志
    Linux下ps命令详解 Linux下ps命令的详细使用方法
    Linux(Unix)时钟同步ntpd服务配置方法
    MySQL 常用命令总结
    MySQL 数据库通过日志恢复
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/11520518.html
Copyright © 2020-2023  润新知