您的位置:首页 > 其它

Codeforces Round#333 div.1 D Acyclic Organic Compounds

2016-05-26 22:04 351 查看
题目大意是给你一棵还没有合并的trie树,要你合并它,然后统计一些傻逼信息。

本题需要一种线性时间复杂度的合并算法,这里直接给代码片了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cassert>
#include<map>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<climits>
#define X first
#define INF 0x3f3f3f3f
#define Y second
#define LL long long
#define DB double
#define pii pair<int,int>
#define MP make_pair
#define pb push_back
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
template<class T>void Read(T& x)
{
x=0;int flag=0,sgn=1;char c;
while(c=getchar())
{
if(c=='-')sgn=-1;
else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
else if(flag)break;
}
x*=sgn;
}
const int MAXN=601000,MAXM=2*MAXN;
int ans1=0, ans2=0;
int n,c[MAXN],ch[MAXN][26],size[MAXN],sz=n;
char s[MAXN];
vector<int> G[MAXN];
void add(int a,int b)
{
G[a].pb(b),G[b].pb(a);
}
bool cmp(int a,int b)
{
return s[a]<s[b];
}
int merge(int u, int v)
{
if(!u||!v)
return u|v;
//fprintf(stderr,"%d\n",sz);
int o=++sz;
assert(o!=1);
//  assert(
size[o]=1;
for(int i=0;i<26;i++)
{
ch[o][i]=merge(ch[u][i],ch[v][i]);
//assert(ch[o][i]!=1);
size[o]+=size[ch[o][i]];
}
return o;
}
void dfs(int u,int f)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==f)
continue;
dfs(v,u);
}
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v==f)
continue;
ch[u][s[v]-'a']=merge(ch[u][s[v]-'a'],v);
}
for(int i=0;i<26;i++)
size[u]+=size[ch[u][i]];
size[u]++;
if(size[u]+c[u]>ans1)
ans1=size[u]+c[u],ans2=1;
else
ans2+=(size[u]+c[u]==ans1);
}
int main()
{
//freopen("4.in","r",stdin);
//freopen("4.out","w",stdout);
Read(n);
sz=n;
for(int i=1;i<=n;i++)
Read(c[i]);
scanf("%s",s+1);
for(int i=1;i<n;i++)
{
int a,b;
Read(a),Read(b);
add(a,b);
}
dfs(1,0);
printf("%d\n%d\n",ans1,ans2);
}


为什么这样是线性的呢?

假设有一个trie树的集合,按照这个算法,每次合并,merge会调用O(min(size[a],size[b]))次,所以调用是所有集合的点数和次,是线性的。

为什么我没有想出来,可能是因为我没怎么写过树的递归合并的题目,也就是代码能力差,结果就算想了也不敢写,甚至因为代码能力的限制而导致思维能力的局限。代码能力像是交通工具,越强就可以把思维承载得越远。我以前一直没有想过代码能力与思维能力之间的联系,总是孤立地看待,这样是有违辩证唯物主义的观点与方法的。今天总算是意识到了,继续加油喽。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: