zoukankan      html  css  js  c++  java
  • Codeforces 1117F Crisp String

    Crisp String

    显然我们只要知道每个状态合不合法我们就能解决这个问题。

    两两枚举相邻的字符, 去找不合法状态。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    bitset<1 << 17> can[17][17];
    char s[N];
    int n, p, ans = inf, c[1 << 17];
    vector<int> pos[17], vc;
    vector<int> to[1 << 17];
    
    bool G[17][17];
    bool ok[1 << 17];
    bool vis[1 << 17];
    
    struct ST {
        int Log[N], dp[N][20];
        void build(char *s, int n) {
            Log[1] = 0;
            for(int i = 2; i <= n; i++) Log[i] = Log[i >> 1] + 1;
            for(int i = 1; i <= n; i++) dp[i][0] = 1 << (s[i] - 'a');
            for(int j = 1; j <= Log[n]; j++)
                for(int i = 1; i <= n; i++)
                    dp[i][j] = dp[i][j - 1] | dp[i + (1 << (j - 1))][j - 1];
        }
        inline int query(int L, int R) {
            if(L > R) return 0;
            int k = Log[R - L + 1];
            return dp[L][k] | dp[R - (1 << k) + 1][k];
        }
    } rmqOr;
    
    int main() {
        scanf("%d%d", &n, &p);
        scanf("%s", s + 1);
        for(int i = 0; i < p; i++)
            for(int j = 0; j < p; j++)
                scanf("%d", &G[i][j]);
    
        for(int i = 0; i < (1 << p); i++) {
            ok[i] = true;
            for(int j = 0; j < p; j++) {
                if(i >> j & 1) continue;
                to[i].push_back(j);
            }
        }
    
        rmqOr.build(s, n);
    
    
        for(int i = 1; i <= n; i++) pos[s[i] - 'a'].push_back(i);
    
        for(int i = 1; i < (1 << p); i++)
            for(int j = 0; j < p; j++)
                if(i >> j & 1) c[i] += SZ(pos[j]);
    
        for(int i = 0; i < p; i++) {
            for(int j = 0; j < p; j++) {
                if(G[i][j]) continue;
                if(i == j) {
                    for(int k = 1; k < SZ(pos[i]); k++)
                        can[i][j][rmqOr.query(pos[i][k - 1] + 1, pos[i][k] - 1)] = true;
                } else {
                    vc.resize(SZ(pos[i]) + SZ(pos[j]));
                    merge(ALL(pos[i]), ALL(pos[j]), vc.begin());
                    for(int k = 1; k < SZ(vc); k++) {
                        if(s[vc[k]] != s[vc[k - 1]]) {
                            can[i][j][rmqOr.query(vc[k - 1] + 1, vc[k] - 1)] = true;
                        }
                    }
                }
                for(int mask = 0; mask < (1 << p); mask++) {
                    if(!can[i][j][mask]) continue;
                    for(auto& k : to[mask]) can[i][j][mask | (1 << k)] = true;
                }
            }
        }
    
        for(int mask = 0; mask < (1 << p); mask++) {
            int fmask = mask ^ ((1 << p) - 1);
            for(int i = 0; i < p && ok[mask]; i++) {
                if(mask >> i & 1) {
                    for(int j = i; j < p && ok[mask]; j++) {
                        if(mask >> j & 1) {
                            if(can[i][j][fmask]) ok[mask] = false;
                        }
                    }
                }
            }
        }
        
        vis[(1 << p) - 1] = true;
        queue<int> que;
        que.push((1 << p) - 1);
        while(!que.empty()) {
            int mask = que.front();
            que.pop();
            chkmin(ans, c[mask]);
            for(int i = 0; i < p; i++) {
                if(mask >> i & 1 && !vis[mask ^ (1 << i)] && ok[mask ^ (1 << i)]) {
                    vis[mask ^ (1 << i)] = true;
                    que.push(mask ^ (1 << i));
                }
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    [模板] 循环数组的最大子段和
    [最短路][几何][牛客] [国庆集训派对1]-L-New Game
    [洛谷] P1866 编号
    1115 Counting Nodes in a BST (30 分)
    1106 Lowest Price in Supply Chain (25 分)
    1094 The Largest Generation (25 分)
    1090 Highest Price in Supply Chain (25 分)
    树的遍历
    1086 Tree Traversals Again (25 分)
    1079 Total Sales of Supply Chain (25 分 树
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10938441.html
Copyright © 2011-2022 走看看