• 「SCOI2016」背单词


    「SCOI2016」背单词

    Lweb 面对如山的英语单词,陷入了深深的沉思,「我怎么样才能快点学完,然后去玩三国杀呢?」。这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,然后凤老师告诉 Lweb ,我知道你要学习的单词总共有 $ n $ 个,现在我们从上往下完成计划表,对于一个序号为 $ x $ 的单词(序号 $ 1 ldots x-1 $ 都已经被填入):

    1. 如果存在一个单词是它的后缀,并且当前没有被填入表内,那他需要吃 $ n imes n $ 颗泡椒才能学会;
    2. 当它的所有后缀都被填入表内的情况下,如果在 $ 1 ldots x - 1 $ 的位置上的单词都不是它的后缀,那么他吃 $ x $ 颗泡椒就能记住它;
    2. 当它的所有后缀都被填入表内的情况下,如果 $ 1 ldots x - 1 $ 的位置上存在是它后缀的单词,所有是它后缀的单词中,序号最大为 $ y $,那么他只要吃 $ x - y $ 颗泡椒就能把它记住。

    Lweb 是一个吃到辣辣的东西会暴走的奇怪小朋友,所以请你帮助 Lweb,寻找一种最优的填写单词方案,使得他记住这 $ n $ 个单词的情况下,吃最少的泡椒。

    Sol
    可以发现一定按着树的顺序填比较优(<n*n)
    那么首先正的贡献是一定的(1+...+n),只考虑负的贡献。
    对于两棵大小不同的子树,记第一颗大小为x,第二棵为y(x<y)
    从每一条边考虑贡献。
    先1后2
    W1=x*(y-1)=xy-x
    先2后1
    W2=xy-y
    W1-W2=y-x>0 先W1更优
     所以把sz按小到大排序就好了。
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define maxn 600005
    using namespace std;
    int n,cnt,tr[maxn][26],p[maxn],f[maxn],sz[maxn],sc;
    long long ans;
    vector<int>G[maxn];
    char ch[maxn];
    void ins(int id){
        int len=strlen(ch);
        int k=0;
        for(int i=len-1;i>=0;i--){
            if(!tr[k][ch[i]-'a'])tr[k][ch[i]-'a']=++cnt;
            k=tr[k][ch[i]-'a'];
        }
        p[k]=id;
    }
    void lj(int t1,int t2){
        f[t1]=t2;G[t2].push_back(t1);
    }
    void add(int k,int la){
        if(p[k])lj(p[k],la);
        for(int i=0;i<26;i++){
            if(tr[k][i])add(tr[k][i],p[k]?p[k]:la);
        }
        if(p[k])sz[la]+=(++sz[p[k]]);
    }
    bool cmp(int a,int b){return sz[a]<sz[b];}
    void dfs(int k,int f){
        if(k)ans+=(++sc)-f;
        int val=sc;
        for(int i=0;i<G[k].size();i++){
            dfs(G[k][i],val);
        }
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            scanf(" %s",ch);ins(i);
        }
        add(0,0);
        
        for(int i=0;i<=n;i++)sort(G[i].begin(),G[i].end(),cmp);
        dfs(0,0);
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    SessionFactory Cache 的配置
    乱码处理问题
    格式化当前日期
    JDK的安装
    内存和对象内存池技术在网游开发中的注意点和应用
    Head First设计模式C++实现Strategy模式
    介绍三种将二进制字节字符转换为ASCII方法
    C++风格的类型转换的用法
    i++循环与i循环的执行效率
    系统程序员成长计划组合的威力(一)
  • 原文地址:https://www.cnblogs.com/liankewei/p/11791612.html
Copyright © 2020-2023  润新知