题目链接 :  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. Python神坑:sum和numpy.sum

    同样的一段代码,在两个python文件里面执行的结果不一样,一个是按照列单位进行sum一个是所有元素进行sum: def distCal(vecA, vecB): return sqrt(sum(po ...

  2. 配置jboss为windows服务

    先确保jdk和jboss的环境变量是正常可用的 1.(下载binaries 2.x.x-windows x86)找到service.bat和jbosssvc.exe两个文件 1.1 binaries ...

  3. ClientDataSet

    TField对象的SetText和GetText事件处理函数 使用TField对象的SetText和GetText事件处理函数可方便的解决字段的代码与代码所对应值的显示问题 TSimpleDatase ...

  4. nginx 代理flask应用的uwsgi配置

    socket代理配置: 关于uwsgi的用法,请自行百度,这里只针对socket文件和端口的不同,进行单一的记录. 这种方式启动的flask应用,由于是通过socket与nginx通信的,所以必须制定 ...

  5. [蓝桥杯]PREV-7.历届试题_连号区间数

    问题描述 小明这些天一直在思考这样一个奇怪而有趣的问题: 在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是: 如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增 ...

  6. C风格字符串和C++string对象的相互转化

    一.C风格的字符串转化为C++的string对象 C++中,string 类能够自动将C 风格的字符串转换成string 对象   #include <iostream> #include ...

  7. 获得驱动器信息卷设备&&Ring3得到磁盘文件系统(NTFS WIN10)

    // GetLogicalDriveStrings.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <Windows ...

  8. Scrapy学习篇(十)之下载器中间件(Downloader Middleware)

    下载器中间件是介于Scrapy的request/response处理的钩子框架,是用于全局修改Scrapy request和response的一个轻量.底层的系统. 激活Downloader Midd ...

  9. POI导入工具类

    前言 导入的通用方法,包括xls.xlsx的取值方法,非空判断方法,空行判断,处理了手机号读取和日期读取格式问题.这几个方法就可以完成简单读取了,有时间我在优化下. maven依赖 <!-- P ...

  10. android 开发 View _14 MotionEvent和事件处理详解,与实践自定义滑动条View

    转载https://blog.csdn.net/huaxun66/article/details/52352469 MotionEvent MotionEvent对象是与用户触摸相关的时间序列,该序列 ...