2018ECfinal J. Philosophical Balance

Posted mangoyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018ECfinal J. Philosophical Balance相关的知识,希望对你有一定的参考价值。

2018ECfinal J. Philosophical Balance

题目大意:

给出一个字符串 (s) ,你需要给每一个 (i) 一个 ([0,1]) 之间的权值 (k_i) ,且满足 (sum k_i=1) 。并且最小化
[ max_{i=1}^n(sum_{j=1}^nlcp(suf(s,j),suf(s,i)) imes k_j) ]
先证明一个比较简单的结论,把 (s) 的后缀树建出来,考虑后缀树的每一个子树,如果子树的根是 (s) 的一个后缀,那么分配到这个子树里面的所有权值必然全部分配到根上。

假设这个子树 (u) 里第 (i) 个节点分配了 (k_i) 的权值,那么对于根的贡献是 (sum{k_i} imes len_{u}) ,考虑对其它点的贡献是每一个权值乘在其某个祖先的 (len) 上,由于 (len) 向上递减,根的贡献固定,那么显然全部放在根上最优。

(f(u)) 为后缀树上 (u) 节点所在子树内部的答案,当 (u) 是后缀节点的时候 (f(u)=len(fa_u)-len(u)) 。否则只需要合并每一个儿子的 (f(v))

考虑儿子与儿子之间是独立的,所有不同儿子之间的贡献都是 (u) ,只需要最后把 (u) 到父亲的边加上去就可以,考虑最优解的一定是每个值相等,感性理解可以得到式子:
[ sum {k_i} = 1 f_1k_1 = f_2k_2=dots= f_mk_m= x \sum frac{x}{f_i}=1 \frac{1}{x} = sum frac{1}{f_i} x = frac{1}{sum frac{1}{f_i}} ]
(mathcal O(n)) 算一算就做完了。

/*program by mangoyang*/
#pragma GCC optimize("Ofast", "inline")
#include <bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
    int ch = 0, f = 0; x = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    if(f) x = -x;
}
#define double long double
const int N = 500005;
vector<int> vec[N];
char s[N];
ll all, val[N]; int n, cnt;
namespace SAM{
    vector<int> g[N];
    int ch[N][26], pos[N], fa[N], len[N], size = 1, tail = 1;
    inline int newnode(int x){ return len[++size] = x, size; }
    inline void ins(int c, int x){
        int p = tail, np = newnode(len[p] + 1); pos[np] = x;
        for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
        if(!p) return (void) (fa[np] = 1, tail = np);
        int q = ch[p][c];
        if(len[q] == len[p] + 1) fa[np] = q;
        else{
            int nq = newnode(len[p] + 1);
            fa[nq] = fa[q], fa[q] = fa[np] = nq;
            for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
            for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
        }tail = np;
    }
    inline void addedge(){
        for(int i = 2; i <= size; i++) g[fa[i]].push_back(i);
    }
    inline double gao(int u, int d){
        if(pos[u]) return d;
        double res = 0;
        for(int i = 0; i < (int) g[u].size(); i++)
            res += 1.0 / gao(g[u][i], len[g[u][i]] - len[u]);
        return 1.0 / res + d;
    }
}
int main(){
    int T; read(T);
    while(T--){
        for(int i = 1; i <= SAM::size; i++){
            SAM::g[i].clear();
            SAM::pos[i] = SAM::fa[i] = SAM::len[i] = 0;
            memset(SAM::ch[i], 0, sizeof(SAM::ch[i]));
        }
        SAM::tail = SAM::size = 1;
        scanf("%s", s + 1); n = strlen(s + 1);
        for(int i = n; i; i--) SAM::ins(s[i] - 'a', i);
        SAM::addedge();
        printf("%.10Lf
", SAM::gao(1, 0));
    }
}

以上是关于2018ECfinal J. Philosophical Balance的主要内容,如果未能解决你的问题,请参考以下文章

IME Starters Try-outs 2018 J. JHADCBEIGF

ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer (最大生成树+LCA求节点距离)

ACM-ICPC 2018 南京赛区网络预赛 - J. Sum (找规律+打表)

ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang

ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang (分块思想)

2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate DFS+剪枝+矩阵旋转