zoukankan      html  css  js  c++  java
  • bzoj 4119 后缀数组 + 并查集

    并查集合并的时候更新信息。注意a[ i ] 有负的。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<vector>
    #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 = 3e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 998244353;
    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;}
    
    //mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    int r[N], sa[N], _t[N], _t2[N], c[N], rk[N], lcp[N], san;
    int maxc = 256;
    
    void buildSa(int *r, int n, int m) {
        int i, j = 0, k = 0, *x = _t, *y = _t2;
        for(i = 0; i < m; i++) c[i] = 0;
        for(i = 0; i < n; i++) c[x[i] = r[i]]++;
        for(i = 1; i < m; i++) c[i] += c[i - 1];
        for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
        for(int k = 1; k <= n; k <<= 1) {
            int p = 0;
            for(i = n - k; i < n; i++) y[p++] = i;
            for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
            for(i = 0; i < m; i++) c[i] = 0;
            for(i = 0; i < n; i++) c[x[y[i]]]++;
            for(i = 1; i < m; i++) c[i] += c[i - 1];
            for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
            swap(x, y);
            p = 1; x[sa[0]] = 0;
            for(int i = 1; i < n; i++) {
                if(y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k])
                    x[sa[i]] = p - 1;
                else x[sa[i]] = p++;
            }
            if(p >= n) break;
            m = p;
         }
         for(i = 1; i < n; i++) rk[sa[i]] = i;
         for(i = 0; i < n - 1; i++) {
            if(k) k--;
            j = sa[rk[i] - 1];
            while(r[i + k] == r[j + k]) k++;
            lcp[rk[i]] = k;
         }
    }
    
    int fa[N], dl[N], dr[N], sz[N], maxVal[N], minVal[N];
    
    int n, maxH, a[N];
    PLL ans[N];
    char s[N];
    
    vector<int> V[N];
    
    int getRoot(int x) {
        return x == fa[x] ? x : fa[x] = getRoot(fa[x]);
    }
    
    int Merge(int u, int v, LL &way, LL &mx) {
        int x = getRoot(u);
        int y = getRoot(v);
        chkmax(mx, 1LL * maxVal[x] * maxVal[y]);
        chkmax(mx, 1LL * minVal[x] * minVal[y]);
        way += 1LL * sz[x] * sz[y];
        fa[y] = x;
        chkmin(dl[x], dl[y]);
        chkmax(dr[x], dr[y]);
        sz[x] += sz[y];
        chkmax(maxVal[x], maxVal[y]);
        chkmin(minVal[x], minVal[y]);
        return x;
    }
    
    void printSuf(int x) {
        for(int i = sa[x]; i < san; i++) putchar((char)r[i]);
        for(int i = 0; i < (sa[x] + 5); i++) putchar(' ');
        printf("sa: %d  lcp: %d
    ", sa[x], lcp[x]);
    }
    
    int main() {
        scanf("%d", &n);
        scanf("%s", s);
        int maxPre = 0;
        int minPre = 0;
        for(int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            chkmax(ans[0].se, 1LL * maxPre * a[i]);
            chkmax(ans[0].se, 1LL * minPre * a[i]);
            chkmax(maxPre, a[i]);
            chkmin(minPre, a[i]);
        }
        ans[0].fi = 1LL * n * (n - 1) / 2;
        for(int i = 0; i < n; i++) {
            r[san++] = s[i];
        }
        r[san] = 0;
        buildSa(r, san + 1, maxc);
    
        for(int i = 1; i <= san; i++) {
            V[lcp[i]].push_back(i);
            chkmax(maxH, lcp[i]);
        }
    
        for(int i = 1; i <= san; i++) {
            fa[i] = dl[i] = dr[i] = i;
            sz[i] = 1;
            maxVal[i] = a[sa[i]];
            minVal[i] = a[sa[i]];
        }
    
        LL way = 0, mx = -INF;
    
        for(int i = maxH; i > 0; i--) {
            for(int j = 0; j < SZ(V[i]); j++) {
                int t = V[i][j];
                Merge(t - 1, t, way, mx);
            }
            ans[i].fi = way;
            ans[i].se = mx;
        }
    
        for(int i = 0; i < n; i++) {
            printf("%lld %lld
    ", ans[i].fi, ans[i].se);
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    【校招面试 之 C/C++】第23题 C++ STL(五)之Set
    Cannot create an instance of OLE DB provider “OraOLEDB.Oracle” for linked server "xxxxxxx".
    Redhat Linux安装JDK 1.7
    ORA-10635: Invalid segment or tablespace type
    Symantec Backup Exec 2012 Agent for Linux 卸载
    Symantec Backup Exec 2012 Agent For Linux安装
    You must use the Role Management Tool to install or configure Microsoft .NET Framework 3.5 SP1
    YourSQLDba介绍
    PL/SQL重新编译包无反应
    MS SQL 监控数据/日志文件增长
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11134616.html
Copyright © 2011-2022 走看看