zoukankan      html  css  js  c++  java
  • BZOJ4567 SCOI2016背单词(trie+贪心)

      倒过来变成查询前缀。考虑怎么排序。第一条代价n*n就相当于inf,说明一个单词的所有前缀都要排在它前面。那么串的依赖关系就是trie的结构。二三条说明代价是Σidi-idfa,那么显然最后的编号应该是trie的一个dfs序(去掉无用节点),并且显然应该先走较小的子树,因为这样使兄弟节点和父亲的编号差更小而不造成其他影响。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define N 510010
    #define M 100010
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int n,trie[N][26],val[N],cnt;
    int size[M],id[M];
    ll ans;
    vector<int> s[M],son[M];
    bool cmp(const int&a,const int&b)
    {
        return size[a]<size[b];
    }
    void ins(vector<int> s,int i)
    {
        int k=0;
        for (int j=0;j<s.size();j++)
        {
            if (!trie[k][s[j]]) trie[k][s[j]]=++cnt;
            k=trie[k][s[j]];
        }
        val[k]=1;
    }
    void build(int k,int from)
    {
        if (val[k]) cnt++,son[from].push_back(cnt),from=cnt;
        for (int i=0;i<26;i++)
        if (trie[k][i]) build(trie[k][i],from);
    }
    void dfs(int k)
    {
        size[k]=1;
        for (int i=0;i<son[k].size();i++)
        {
            dfs(son[k][i]);
            size[k]+=size[son[k][i]];
        }
        sort(son[k].begin(),son[k].end(),cmp);
    }
    void calc(int k,int from)
    {
        id[k]=++cnt;ans+=id[k]-id[from];
        for (int i=0;i<son[k].size();i++)
        calc(son[k][i],k);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4567.in","r",stdin);
        freopen("bzoj4567.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++)
        {
            s[i].push_back(getc()-'a');
            char c=getchar();
            while (c>='a'&&c<='z') s[i].push_back(c-'a'),c=getchar();
            reverse(s[i].begin(),s[i].end());
            ins(s[i],i);
        }
        cnt=0;
        build(0,0);
        dfs(0);
        cnt=-1;
        calc(0,0);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    jFinal基于maven简单的demo
    quartz定时任务
    cors解决跨越问题
    poi导出excel
    layui富文本编译器后台获取图片路径
    HttpClient短信接口
    js分页
    El表达式日期处理
    【传智播客】Libevent学习笔记(二):创建event_base
    【传智播客】Libevent学习笔记(一):简介和安装
  • 原文地址:https://www.cnblogs.com/Gloid/p/9890265.html
Copyright © 2011-2022 走看看