zoukankan      html  css  js  c++  java
  • BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )

    求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) 

    -----------------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    typedef long long ll;
     
    const ll INF = -1LL << 60;
    const int maxn = 300009;
     
    char S[maxn];
    int w[maxn], N;
    int cnt[maxn], Sa[maxn], Rank[maxn], Height[maxn];
    int mx[maxn], mn[maxn], fa[maxn], sz[maxn], r[maxn];
    ll ans[maxn], tot[maxn];
     
    void Init() {
    scanf("%d%s", &N, S);
    for(int i = 0; i < N; i++) scanf("%d", w + i);
    S[N++] = '$';
    }
     
    void Build() {
    int m = 255, *x = Height, *y = Rank;
    for(int i = 0; i < m; i++) cnt[i] = 0;
    for(int i = 0; i < N; i++) cnt[x[i] = S[i]]++;
    for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
    for(int i = N; i--; ) Sa[--cnt[x[i]]] = i;
    for(int k = 1, p = 0; k <= N; k <<= 1, p = 0) {
    for(int i = N - k; i < N; i++) y[p++] = i;
    for(int i = 0; i < N; i++)
    if(Sa[i] >= k) y[p++] = Sa[i] - k;
    for(int i = 0; i < m; i++) cnt[i] = 0;
    for(int i = 0; i < N; i++) cnt[x[y[i]]]++;
    for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
    for(int i = N; i--; ) Sa[--cnt[x[y[i]]]] = y[i];
    swap(x, y), x[Sa[0]] = 0, p = 1;
    for(int i = 1; i < N; i++) {
    if(y[Sa[i]] != y[Sa[i - 1]] || y[Sa[i] + k] != y[Sa[i - 1] + k]) p++;
    x[Sa[i]] = p - 1;
    }
    if((m = p) >= N) break;
    }
    for(int i = 0; i < N; i++) Rank[Sa[i]] = i;
    Height[0] = 0;
    for(int i = 0, h = 0; i < N; i++) if(Rank[i]) {
    if(h) h--;
    while(S[i + h] == S[Sa[Rank[i] - 1] + h]) h++;
    Height[Rank[i]] = h;
    }
    }
     
    int Find(int x) {
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
    }
     
    bool Cmp(const int &l, const int &r) {
    return Height[l] > Height[r];
    }
     
    inline void Max(ll &x, ll t) {
    if(t > x) x = t;
    }
    inline void Max(int &x, int t) {
    if(t > x) x = t;
    }
    inline void Min(int &x, int t) {
    if(t < x) x = t;
    }
     
    void Work() {
    for(int i = 0; i < N; i++) {
    sz[i] = 1;
    r[i] = fa[i] = i;
    mx[i] = mn[i] = w[i];
    tot[i] = 0;
    ans[i] = INF;
    }
    sort(r, r + N, Cmp);
    for(int i = 0; i < N; i++) if(r[i] > 1) {
    int u = Find(Sa[r[i]]), v = Find(Sa[r[i] - 1]);
    if(u == v) continue;
    tot[Height[r[i]]] += ll(sz[u]) * sz[v];
    Max(ans[Height[r[i]]], max(ll(mx[u]) * mx[v], ll(mn[u]) * mn[v]));
    fa[u] = v, sz[v] += sz[u];
    Max(mx[v], mx[u]);
    Min(mn[v], mn[u]);
    }
    for(int i = Height[r[0]]; i--; )
    tot[i] += tot[i + 1], Max(ans[i], ans[i + 1]);
    for(int i = 0; i + 1 < N; i++)
    printf("%lld %lld ", tot[i], ans[i] != INF ? ans[i] : 0);
    }
     
    int main() {
    Init();
    Build();
    Work();
    return 0;
    }

    -----------------------------------------------------------------------------------

  • 相关阅读:
    liunx 用户切换 su sudo
    tomcat 虚拟目录
    如何用vue封装一个防用户删除的平铺页面的水印组件
    webpack入门学习手记(一)
    理解跨域及常用解决方案
    封装一个优雅的element ui表格组件
    使用Koa.js离不开这十个中间件
    深入理解let和var的区别
    编辑器IDE之VSCode
    WTF!! Vue数组splice方法无法正常工作
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5156166.html
Copyright © 2011-2022 走看看