Lomsat gelral cf-600e

http://codeforces.com/contest/600/problem/E

暴力启发式合并就行了

提示:set的swap的复杂度是常数,这方面可以放心

我先打了一个很naive的算法

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<set>
 5 #include<map>
 6 using namespace std;
 7 typedef long long LL;
 8 typedef pair<LL,LL> P;
 9 typedef set<P> s;
10 //P(颜色出现次数,颜色编号)
11 typedef map<LL,LL> m;
12 //颜色编号->颜色出现次数
13 typedef pair<s,m> P2;
14 LL n,anss[100100],c[100100];
15 vector<LL> e[100100];
16 P2 dfs(LL u,LL fa)
17 {
18     P2 t,ans;
19     ans.first.emplace(1,c[u]);
20     ans.second[c[u]]=1;
21     for(auto v:e[u])
22         if(v!=fa)
23         {
24             t=dfs(v,u);
25             if(t.second.size()>ans.second.size())    swap(t,ans);
26             for(auto it:t.second)
27             {
28                 ans.first.erase(P(ans.second[it.first],it.first));
29                 ans.second[it.first]+=it.second;
30                 ans.first.emplace(ans.second[it.first],it.first);
31             }
32         }
33     int maxsz=ans.first.rbegin()->first;
34     for(auto it=ans.first.rbegin();it!=ans.first.rend()&&it->first==maxsz;it++)    anss[u]+=it->second;
35     return ans;
36 }
37 int main()
38 {
39     LL i,x,y;
40     scanf("%lld",&n);
41     for(i=1;i<=n;i++)    scanf("%lld",&c[i]);
42     for(i=1;i<n;i++)
43     {
44         scanf("%lld%lld",&x,&y);
45         e[x].push_back(y);e[y].push_back(x);
46     }
47     dfs(1,0);
48     for(i=1;i<=n;i++)    printf("%lld ",anss[i]);
49     return 0;
50 }
View Code

毫不意外的被卡掉了~看第34行,怎么看都不对嘛

有两种解决方法:

第一种:每一个节点dfs的时候额外返回一个值,记录当前子树的答案。

第二种:将set换成另一个map<int,int>,记录颜色出现次数->编号之和

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 using namespace std;
 6 typedef long long LL;
 7 typedef map<LL,LL> m;
 8 //颜色出现次数->编号之和
 9 //颜色编号->颜色出现次数
10 typedef pair<m,m> P2;
11 LL n,anss[100100],c[100100];
12 vector<LL> e[100100];
13 P2 dfs(LL u,LL fa)
14 {
15     P2 t,ans;
16     ans.first[1]=c[u];
17     ans.second[c[u]]=1;
18     for(auto v:e[u])
19         if(v!=fa)
20         {
21             t=dfs(v,u);
22             if(t.second.size()>ans.second.size())    swap(t,ans);
23             for(auto it:t.second)
24             {
25                 ans.first[ans.second[it.first]]-=it.first;
26                 ans.second[it.first]+=it.second;
27                 ans.first[ans.second[it.first]]+=it.first;
28             }
29         }
30     anss[u]=ans.first.rbegin()->second;
31     return ans;
32 }
33 int main()
34 {
35     LL i,x,y;
36     scanf("%lld",&n);
37     for(i=1;i<=n;i++)    scanf("%lld",&c[i]);
38     for(i=1;i<n;i++)
39     {
40         scanf("%lld%lld",&x,&y);
41         e[x].push_back(y);e[y].push_back(x);
42     }
43     dfs(1,0);
44     for(i=1;i<=n;i++)    printf("%lld ",anss[i]);
45     return 0;
46 }

也可以将每个节点dfs返回的值改成全局变量(似乎可以避免一些玄学的常数问题)

posted @ 2018-03-14 20:50  hehe_54321  阅读(131)  评论(0编辑  收藏  举报
AmazingCounters.com