1 条题解

  • 0
    @ 2026-10-25 21:35:24

    思路

    反向Trie连接最近单词后缀,先学祖先形成树;相邻子树交换使贡献差为两子树大小之差,故按子树大小递增遍历,不能仅按单词长度或字典序贪心;n十万、总长51万,答案可超过32位。

    参考程序(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    struct Node{int ch[26];int word;Node(){memset(ch,0,sizeof(ch));word=0;}};
    int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int n;cin>>n;vector<Node>tr(1);vector<vector<int>>child(n+1);for(int id=1;id<=n;id++){string s;cin>>s;int v=0;for(auto it=s.rbegin();it!=s.rend();++it){int c=*it-'a';if(!tr[v].ch[c]){int u=tr.size();tr[v].ch[c]=u;tr.emplace_back();}v=tr[v].ch[c];}tr[v].word=id;}
    vector<pair<int,int>>q(1,{0,0});while(!q.empty()){auto p=q.back();q.pop_back();int v=p.first,ancestor=p.second;if(tr[v].word){int u=tr[v].word;child[ancestor].push_back(u);ancestor=u;}for(int c=0;c<26;c++)if(tr[v].ch[c])q.push_back({tr[v].ch[c],ancestor});}
    vector<int>order(1,0),sz(n+1,1);for(int i=0;i<(int)order.size();i++)for(int v:child[order[i]])order.push_back(v);for(int i=n;i>0;i--)for(int v:child[order[i]])sz[order[i]]+=sz[v];for(auto &a:child)sort(a.begin(),a.end(),[&](int u,int v){return sz[u]<sz[v];});vector<int>st(1,0),pos(n+1);int timer=0;long long ans=0;while(!st.empty()){int u=st.back();st.pop_back();if(u)pos[u]=++timer;int next=pos[u]+1;for(int v:child[u]){ans+=next-pos[u];next+=sz[v];}for(auto it=child[u].rbegin();it!=child[u].rend();++it)st.push_back(*it);}cout<<ans<<'\n';}
    
    • 1

    信息

    ID
    1525
    时间
    1000ms
    内存
    256MiB
    难度
    普及+
    标签
    递交数
    1
    已通过
    1
    上传者