「SCOI2016」背单词
「SCOI2016」背单词
Lweb 面对如山的英语单词,陷入了深深的沉思,「我怎么样才能快点学完,然后去玩三国杀呢?」。这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,然后凤老师告诉 Lweb ,我知道你要学习的单词总共有 个,现在我们从上往下完成计划表,对于一个序号为 的单词(序号 都已经被填入):
1. 如果存在一个单词是它的后缀,并且当前没有被填入表内,那他需要吃 颗泡椒才能学会;
2. 当它的所有后缀都被填入表内的情况下,如果在 的位置上的单词都不是它的后缀,那么他吃 颗泡椒就能记住它;
2. 当它的所有后缀都被填入表内的情况下,如果 的位置上存在是它后缀的单词,所有是它后缀的单词中,序号最大为 ,那么他只要吃 颗泡椒就能把它记住。
Lweb 是一个吃到辣辣的东西会暴走的奇怪小朋友,所以请你帮助 Lweb,寻找一种最优的填写单词方案,使得他记住这 个单词的情况下,吃最少的泡椒。
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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2018-11-04 地理课(geography)
2018-11-04 数学课(math)
2018-11-04 物理课(physics)