题目链接 :  http://codeforces.com/gym/100781/attachments

A-Adjoin the Network

题意大概是有多棵树(也可能是一颗),现在要把它们合并成一颗树,且保证最终这棵树的最远点对最小,求最后的这棵树的最长链(最远点对)的长度。

练习赛时想的是我们在每棵树上跑出最长链,并找到中间点,然后以所有"最长链"中的最长链的中间点为根节点,其他"最长链"的中间点直接与这个根节点相连即可构造出最远点对最小的大树。然而并不知道怎么找到最长链的中间点,跑最长链也有点不熟。

其实这题只要有上面构造的思路,然后求出所有最长链的长度即可。因为最后这棵最远点对最小的大树其最长链的只可能有三种情况(对应三种推出方式):

1. 最长链的长度

2. 最长链的"一半"长度 + 次长链的"一半"长度 + 1

3. 次长链的"一半"长度 + 季长链的"一半"长度 + 1

ps : 以上的"一半"是偶取半,奇取半+1 这个画下图就能明白

然后我们只需要跑出每棵小树的"最长链"长度排序计算即可。

 #include <bits/stdc++.h>
using namespace std;
#define pb(x) push_back((x)); const int INF=0x3f3f3f3f;
vector< int > G[+];
bool vis[+];
int d[+][];
vector< int > lian;
int longest; void dfs1(int me, int fa){
vis[me]=true;
for(auto son:G[me]){
if(son==fa) continue;
dfs1(son,me);
if(d[son][]+>=d[me][]){
d[me][]=d[me][];
d[me][]=d[son][]+;
}
}
} void dfs2(int me ,int fa){
if(fa!=-){
if(d[me][]+==d[fa][]) d[me][]=max(d[me][]+d[me][],d[me][]++d[fa][]);
else d[me][]=max(d[me][]+d[me][],d[me][]++d[fa][]);
}
else{
d[me][]=d[me][]+d[me][];
}
for(auto son: G[me]){
if(son==fa) continue;
dfs2(son,me);
}
longest=max(longest,d[me][]);
} bool cmp(int a,int b){
return a>b;
} int getR(int L){
if(L%) return L/+;
return L/;
} int main(){
int N,M;
scanf("%d%d",&N,&M);
for(int i=;i<N;++i) {
G[i].clear();
vis[i]=false;
}
lian.clear();
for(int i=;i<M;++i){
int u,v;
scanf("%d%d",&u,&v);
G[u].pb(v);
G[v].pb(u);
}
for(int i=;i<N;++i){
if(vis[i]==false){
longest=-;
dfs1(i,-);
//printf("%d : %d\n",i,d[i][0]+d[i][1]);
dfs2(i,-);
lian.pb(longest);
}
}
sort(lian.begin(),lian.end(),cmp);
int ans=-;
if(lian.size()>) ans=max(ans,lian[]);
if(lian.size()>) ans=max(ans,getR(lian[])+getR(lian[])+);
if(lian.size()>) ans=max(ans,getR(lian[])+getR(lian[])+);
printf("%d\n",ans);
return ;
}

开始的时候只用一次dfs跑,这只能跑出根节点的最长链,还要第二次dfs。 简单说明: d[i][0]为i点固定方法最深度 ,d[i][1]为次深度,d[i][2]为经过i点的最长链长度。

(求最远点对的方法以前学过,这题应该很快写出来才是,惭愧惭愧。

E-Entertainment Box

最开始学贪心的例子是给出一系列课程(知道开始与结束时间),需要尽可能安排上更多的课程,解决方案是贪心结束时间早的。

而这道题相当于给了N个时间段,K个轨道可以跑时间段,要求能上最多的课程数。(题目是录节目,我说成上课,其实一个意思)

想法还是贪心结束时间靠前的,用一个数据结构模拟K个轨道跑课程。

错误代码:

 #include<bits/stdc++.h>
using namespace std;
#define fst first
#define scd second typedef long long ll;
typedef pair<ll , ll > pii;
queue< pii > Q;
pii pro[+];
int _id[+]; bool cmp(int i,int j){
if(pro[i].scd!=pro[j].scd)return pro[i].scd<pro[j].scd;
return pro[i].fst<pro[i].fst;
} int main(){
int N,K;
while(~scanf("%d%d",&N,&K)){
//printf("N K :%d %d\n",N,K);
for(int i=;i<=N;++i){
ll xx,yy;
scanf("%lld%lld",&xx,&yy);
_id[i]=i;
pro[i]=make_pair(xx,yy);
}
sort(_id+,_id++N,cmp);
while(!Q.empty()) Q.pop();
//for(int i=1;i<=N;++i) printf("record %d : %lld %lld\n",i,pro[_id[i]].fst,pro[_id[i]].scd);
int cnt=;
for(int i=;i<=K;++i) Q.push(make_pair(-1ll,0ll));
//printf("N K :%d %d\n",N,K);
for(int i=;i<=N;++i){
pii can=pro[_id[i]];
while((!Q.empty())&&can.fst>=Q.front().scd) Q.pop();
if(Q.size()<K){
Q.push(can);
//printf("record %d : %lld %lld\n",i,pro[_id[i]].fst,pro[_id[i]].scd);
cnt++;
}
}
printf("%d\n",cnt);
}
return ;
}

插入新课程时队列会弹出所有已经早于新课程开始时间就结束的课程,然而这是不行的。

5 3

1 2

1 3

1 5

4 6

1 7

这是队友出的Hack数据,如果(4  6) 入队 ,(1  2) 和(1  3)都会被弹出,然后 (1, 7)  反而可以被多计一次了。

正确更换课程应该最多更换一个早于新课程开始时间就结束的且最近的课程。这时候我们需要用 multiset 。(之前队列不行也可以理解为我们已经贪结束时间了,不能随便按自然时间流逝弹出所有早于新课程开始时间就结束的课程)

AC代码:

 #include <bits/stdc++.h>
using namespace std;
#define fst first
#define scd second
typedef pair<int ,int > pii;
multiset <int > mtst; bool cmp(pii a, pii b){
if(a.scd!=b.scd) return a.scd<b.scd;
return a.fst<b.fst;
} pii P[+]; int main(){
int N,K;
scanf("%d%d",&N,&K);
for(int i=;i<N;++i){
scanf("%d%d",&P[i].fst,&P[i].scd);
//printf("%d : %d %d\n",i,P[i].fst,P[i].scd);
}
sort(P,P+N,cmp);
//for(int i=0;i<N;++i) printf("%d : %d %d\n",i,P[i].fst,P[i].scd);
for(int i=;i<K;++i){
mtst.insert();
}
multiset< int > :: iterator p;
int cnt=;
for(int i=;i<N;++i){
int l=P[i].fst,r=P[i].scd;
p=mtst.upper_bound(l);
if(p==mtst.begin()) continue;
p--;
mtst.erase(p);
mtst.insert(r);
//printf("r : %d\n",r);
cnt++;
}
printf("%d\n",cnt);
return ;
}

2015-2016 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2015)的更多相关文章

  1. (寒假GYM开黑)2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)

    layout: post title: 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018) author: &qu ...

  2. Codeforces Gym101572 B.Best Relay Team (2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017))

    2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017) 今日份的训练,题目难度4颗星,心态被打崩了,会的算法太少了,知 ...

  3. 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)- D. Delivery Delays -二分+最短路+枚举

    2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)- D. Delivery Delays -二分+最短路+枚举 ...

  4. 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)-E. Explosion Exploit-概率+状压dp

    2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)-E. Explosion Exploit-概率+状压dp [P ...

  5. 2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017) Solution

    A - Airport Coffee 留坑. B - Best Relay Team 枚举首棒 #include <bits/stdc++.h> using namespace std; ...

  6. 2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)

    A. Airport Coffee 设$f_i$表示考虑前$i$个咖啡厅,且在$i$处买咖啡的最小时间,通过单调队列优化转移. 时间复杂度$O(n)$. #include<cstdio> ...

  7. Codeforces Gym101572 G.Galactic Collegiate Programming Contest (2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017))

    Problem G Galactic Collegiate Programming Contest 这个题题意读了一会,就是几个队参加比赛,根据实时的信息,问你1号队的实时排名(题数和罚时相同的时候并 ...

  8. 模拟赛小结:2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)

    比赛链接:传送门 本场我们队过的题感觉算法都挺简单的,不知道为啥做的时候感觉没有很顺利. 封榜后7题,罚时1015.第一次模拟赛金,虽然是北欧的区域赛,但还是有点开心的. Problem B Best ...

  9. ACM ICPC, JUST Collegiate Programming Contest (2018) Solution

    A:Zero Array 题意:两种操作, 1 p v  将第p个位置的值改成v  2  查询最少的操作数使得所有数都变为0  操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能 ...

随机推荐

  1. 19/03/13python学习笔记

    1.变量命名 name1 = 1 name2 = "sunj" 2.命名变量的规则 (1.变量是字母.数字.下划线的组合(2.不能以数字开头(3.不能用关键词命名变量(4.变量中间 ...

  2. istream不是std的成员

    如果报错信息为:istream不是std的成员,那么有两种可能 1.没有包含iostream库文件 2.#ifndef 和#endif使用错误,致使包含的iostream的头文件没有被主函数包含

  3. CenterOS7.5中搭建wordpress

    centeros7.5中搭建wordpress 1.环境 云平台:华为云 服务器操作系统:CentOS7.: 博客部署的服务器:Apache HTTP: 数据库:mysql: 框架:wordpress ...

  4. 2、php中字符串单引号好和双引号的区别

    使用单引号和双引号的主要区别是:单引号定义的字符串中出现的变量和转义序列不会被变量的值代替,而双引号中使用变量名会显示该变量的值.

  5. 如何增加黑客通过ssh入侵的难度--保护ssh的三把锁

    源文档:https://blog.csdn.net/cnbird2008/article/details/6130696 简介 如果需要远程访问计算机并启用了 Secure Shell (SSH) 连 ...

  6. 测试技术/网游Bug分析/单机修改 视频教程

    早期做的一些视频,测试技术/Bug讲解/单机修改,有兴趣的同学自行下载看吧 由于是早期录制的,有口误多包涵... 链接: http://pan.baidu.com/s/1i5JUKPf 密码: a1x ...

  7. Windows 下最佳的 C++ 开发的 IDE 是什么?

    作者:渡世白玉链接:https://www.zhihu.com/question/19589089/answer/30312199来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  8. Android中的Sqlite中的onCreate方法和onUpgrade方法的执行时机

    1.今天在做数据库升级的时候,遇到一个问题,就是onCreate方法和onUpgrade方法的执行时机的问题,这个当时在操作的时候,没有弄清楚,很是迷糊,后来看了相关的博客由于转发受限所以copy了一 ...

  9. gradle重复依赖终极方案解决办法

    buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build: ...

  10. KMS服务器激活WIN方法

    KMS激活的过程简单说就是:欲激活的电脑向KMS服务器请求,KMS服务器做出回应同意激活. KMS激活软件是将KMS服务器用一段代码来模拟,做成一个可执行的程序(即所谓的KMS伺服器).KMS激活软件 ...