3797714 2014 - 10 - 12 21:58 : 19
Accepted 3820 C++
1350 70240
zz_1215

比較麻烦的一道题吧,開始的时候不停的段异常,后面知道是爆栈了,然后用数组模拟递归,才ac了

思路挺简单的,先找到这个树的直径,单独拿出来,能够证明最后选的两个点一定是在直径上的。我就不证了

然后求出这条直径上的每一个点向外延伸的最远距离

对这个距离做两次RMQ,第一次是对于往左边计算最大距离,所以要这个距离的序列要依次+1,+2,+3.......+n-1,+n

第二次是对于往右边计算最大距离。所以序列要+n,+n-1........+3,+2,+1

然后确定一个左起点。二分右起点

最后的复杂度是O(n*log(n))

实现起来还是挺复杂的,吐槽下这样的考代码能力的题

最后有一点提醒下,向外延伸的时候不要忘了向父节点的方向延伸。由于这个我又wa了一次

#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<cassert>
#include<cstring>
#include<iomanip>
using namespace std;
#ifdef _WIN32
#define i64 __int64
#define out64 "%I64d\n"
#define in64 "%I64d"
#else
#define i64 long long
#define out64 "%lld\n"
#define in64 "%lld"
#endif
/************ for topcoder by zz1215 *******************/
#define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define FOR(i,a,b) for( int i = (a) ; i <= (b) ; i ++)
#define FF(i,a) for( int i = 0 ; i < (a) ; i ++)
#define FFD(i,a,b) for( int i = (a) ; i >= (b) ; i --)
#define S64(a) scanf(in64,&a)
#define SS(a) scanf("%d",&a)
#define LL(a) ((a)<<1)
#define RR(a) (((a)<<1)+1)
#define pb push_back
#define pf push_front
#define X first
#define Y second
#define CL(Q) while(!Q.empty())Q.pop()
#define MM(name,what) memset(name,what,sizeof(name))
#define MC(a,b) memcpy(a,b,sizeof(b))
#define MAX(a,b) ((a)>(b)? (a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define read freopen("out.txt","r",stdin)
#define write freopen("out2.txt","w",stdout) const int inf = 0x3f3f3f3f;
const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
const double oo = 10e9;
const double eps = 10e-9;
const double pi = acos(-1.0);
const int maxn = 211111; struct Node{
int now;
int to;
int h;
bool operator < (const Node & cmp) const{
return h>cmp.h;
}
}node; int n;
vector<Node>g[maxn];
int dfv[maxn];
int dfn[maxn];
int t[maxn];
int h[maxn]; int df;
vector<int>s;
vector<int>si;
bool vis[maxn];
vector<int>line;
int a[maxn];
int ax[maxn][20];
int dx[maxn][20];
int lg2[maxn];
bool isline[maxn]; void dfs(){
for (int i = 1; i <= n; i++){
vis[i] = false;
}
df = 1;
s.clear();
si.clear();
s.push_back(1);
si.push_back(0);
vis[1] = true;
int now, to, id;
while (!s.empty()){
now = s.back();
id = si.back();
if (id < g[now].size()){
to = g[now][id].to;
si.back()++;
if (!vis[to]){
vis[to] = true;
t[to] = now;
s.push_back(to);
si.push_back(0);
}
}
else{
dfv[df] = s.back();
dfn[s.back()] = df++;
s.pop_back();
si.pop_back();
}
}
} int find_len(int now){
if (g[now].size() >= 2){
return g[now][0].h + g[now][1].h;
}
else if (g[now].size() == 1){
return g[now][0].h;
}
else{
return 0;
}
} void get_line(int now){
if (g[now].size() >= 2){
int t1 = g[now][0].to;
int t2 = g[now][1].to;
isline[now] = true;
while (true){
isline[t1] = true;
line.push_back(t1);
if (g[t1].size() > 0){
t1 = g[t1][0].to;
}
else{
break;
}
} reverse(line.begin(), line.end());
line.push_back(now);
while (true){
isline[t2] = true;
line.push_back(t2);
if (g[t2].size() > 0){
t2 = g[t2][0].to;
}
else{
break;
}
}
}
else if(g[now].size() ==1){
while (true){
isline[now] = true;
line.push_back(now);
if (g[now].size() > 0){
now = g[now][0].to;
}
else{
break;
}
}
}
} int max_way(int now){
int to;
int re = 0;
for (int i = 0; i < g[now].size(); i++){
to = g[now][i].to;
if (!isline[to]){
re = max(re, g[now][i].h);
}
}
return re;
} void sparse_table(){
for (int i = 0; i < line.size(); i++){
ax[i][0] = a[i]+i;
dx[i][0] = a[i]+(int)line.size()-1-i;
}
for (int step = 1; (1 << step) < line.size(); step++){
for (int i = 0; i < line.size(); i++){
ax[i][step] = ax[i][step - 1];
dx[i][step] = dx[i][step - 1];
if (i + (1 << (step - 1)) < line.size()){
ax[i][step] = max(ax[i][step], ax[i + (1 << (step - 1))][step - 1]);
dx[i][step] = max(dx[i][step], dx[i + (1 << (step - 1))][step - 1]);
}
}
}
} int max_a(int l, int r){
return max(ax[l][lg2[r - l + 1]], ax[r - (1 << lg2[r - l + 1]) + 1][lg2[r - l + 1]]);
} int max_d(int l, int r){
return max(dx[l][lg2[r - l + 1]], dx[r - (1 << lg2[r - l + 1]) + 1][lg2[r - l + 1]]);
} int find(int l, int r){
int mid = (r + l) / 2;
return max(max_a(l, mid) - l, max_d(mid+1,r)-( (int)line.size()-1-r ) );
} int back[maxn]; void find_back(){
for (int i = 1; i <= n; i++){
back[i] = 0;
}
queue<int>q;
q.push(1);
int now, to,fa,temp;
while (!q.empty()){
now = q.front();
q.pop();
if (t[now]){
fa = t[now];
back[now] = 1 + back[fa];
temp = 0;
if (g[fa][0].to == now){
if (g[fa].size() >= 2){
temp = g[fa][1].h+1;
}
}
else{
temp = g[fa][0].h;
}
back[now] = max(back[now], temp);
}
for (int i = 0; i < g[now].size(); i++){
q.push(g[now][i].to);
}
}
} void start(){
dfs();
for (int i = 1; i <= n; i++){
h[i] = 0;
} vector<Node>gg;
int now, to;
for (now = 1; now <= n; now++){
gg.clear();
for (int i = 0; i < g[now].size(); i++){
to = g[now][i].to;
if (to != t[now]){
gg.push_back(g[now][i]);
}
}
g[now] = gg;
} for (int x = 1; x < df; x++){
now = dfv[x];
for (int i = 0; i < g[now].size(); i++){
to = g[now][i].to;
h[now] = max(h[now], h[to] + 1);
}
} for (now = 1; now <= n; now++){
for (int i = 0; i < g[now].size(); i++){
to = g[now][i].to;
g[now][i].h = h[to] + 1;
}
} for (now = 1; now <= n; now++){
sort(g[now].begin(), g[now].end());
} int id;
int len = -1;
int temp;
for (now = 1; now <= n; now++){
temp = find_len(now);
if (temp > len){
len = temp;
id = now;
}
} for (int i = 1; i <= n; i++){
isline[i] = false;
}
line.clear();
get_line(id); find_back(); for (int i = 0; i < line.size(); i++){
a[i] = max_way(line[i]);
if (line[i] == id){
a[i] = max(a[i], back[id]);
}
} sparse_table(); int ans=inf;
int left;
int right;
int l, r;
for (int lend = 0; lend < line.size(); lend++){
l = lend;
r = line.size() - 1;
while (l + 2 < r){
int mid = (l + r) / 2;
if (find(lend, mid) > (int)line.size() - 1 - mid){
r = mid;
}
else{
l = mid;
} }
for (int x = l; x <= r; x++){
temp = max(find(lend, x), (int)line.size() - 1 - x);
temp = max(temp, lend);
if (temp < ans){
ans = temp;
left = lend;
right = x;
}
}
}
cout << ans << " " << line[left] << " " << line[right] << endl;
} int main(){
for (int i = 0; i < 20; i++){
if ((1 << i) < maxn){
lg2[1 << i] = i;
}
}
for (int i = 3; i < maxn; i++){
if (!lg2[i]){
lg2[i] = lg2[i - 1];
}
} int T;
cin >> T;
while (T--){
cin >> n;
for (int i = 1; i <= n; i++){
g[i].clear();
}
node.h = 0;
for (int i = 1; i <= n - 1; i++){
// cin >> node.now >> node.to;
SS(node.now); SS(node.to);
g[node.now].push_back(node);
swap(node.now, node.to);
g[node.now].push_back(node);
}
start();
}
return 0;
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

ZOJ 3820 2014ACM/ICPC牡丹江司B称号的更多相关文章

  1. ZOJ3819 ACM-ICPC 2014 亚洲区域赛的比赛现场牡丹江司A称号 Average Score 注册标题

    Average Score Time Limit: 2 Seconds      Memory Limit: 131072 KB Bob is a freshman in Marjar Univers ...

  2. ZOJ3822 ACM-ICPC 2014 亚洲杯赛事现场牡丹江司D称号Domination 可能性DP

    Domination Time Limit: 8 Seconds      Memory Limit: 131072 KB      Special Judge Edward is the headm ...

  3. HDU 5127.Dogs' Candies-STL(vector)神奇的题,set过不了 (2014ACM/ICPC亚洲区广州站-重现赛(感谢华工和北大))

    周六周末组队训练赛. Dogs' Candies Time Limit: 30000/30000 MS (Java/Others)    Memory Limit: 512000/512000 K ( ...

  4. HDU 5135.Little Zu Chongzhi's Triangles-字符串 (2014ACM/ICPC亚洲区广州站-重现赛)

    Little Zu Chongzhi's Triangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 ...

  5. HDU 5131.Song Jiang's rank list (2014ACM/ICPC亚洲区广州站-重现赛)

    Song Jiang's rank list Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java ...

  6. zoj 3820 Building Fire Stations(二分法+bfs)

    题目链接:zoj 3820 Building Fire Stations 题目大意:给定一棵树.选取两个建立加油站,问说全部点距离加油站距离的最大值的最小值是多少,而且随意输出一种建立加油站的方式. ...

  7. 2014ACM/ICPC亚洲区域赛牡丹江站现场赛-A ( ZOJ 3819 ) Average Score

    Average Score Time Limit: 2 Seconds      Memory Limit: 65536 KB Bob is a freshman in Marjar Universi ...

  8. 2014ACM/ICPC亚洲区域赛牡丹江站现场赛-K ( ZOJ 3829 ) Known Notation

    Known Notation Time Limit: 2 Seconds      Memory Limit: 65536 KB Do you know reverse Polish notation ...

  9. 2014ACM/ICPC亚洲区域赛牡丹江站现场赛-I ( ZOJ 3827 ) Information Entropy

    Information Entropy Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge Information ...

随机推荐

  1. Linux iptables简单配置

    #!/bin/sh#modprobe ipt_MASQUERADEmodprobe ip_conntrack_ftpmodprobe ip_nat_ftpiptables -Fiptables -t ...

  2. [IOS]UIWebView实现保存页面和读取服务器端json数据

    如何通过viewView保存访问过的页面?和如何获取并解析服务器端发送过来的json数据?通过一个简单的Demo来学习一下吧! 操作步骤: 1.创建SingleViewApplication应用,新建 ...

  3. Objective-C NSObject 的实现分析(2014-10-23更新)

    NSObject 的实现分析 转载请注名出处 http://blog.csdn.net/uxyheaven iOS 的 NSObject 类没有开源, 可是呢 runtime开源了,里面有个类 Obj ...

  4. Android至ViewPager添加切换动画——使用属性动画

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/44200623 ViewPager作为Android最经常使用的的组件之中的一个.相 ...

  5. [置顶] JUnit入门教程(二)

    一:介绍 接着上次的课程,今天我们学习JUnit4的新特性 assertThat()方法,这种方式和其余的assert方法比起来,更加接进英语. 二:分析API API中的例子: 参数 T Actua ...

  6. Android在Context详细解释 ---- 你不知道Context

                                                                                                         ...

  7. python学习笔记--for循环

    推荐一个学习语言的网站:http://www.codecademy.com 有教程,可以边学边写,蛮不错的. for循环: 1.for loops allow us to iterate throug ...

  8. linux sort,uniq,cut,wc命令详解 (转)

    sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序. sort语法 ...

  9. oracle 关于日期格式转换与使用

    在oracle中我们经常会和日期打交道,在做报表的时候经常会用日报,周报,月报之类的条件进行分组: 我写了些例子来启发下大脑 select Sysdate from dual select to_ch ...

  10. Java乔晓松-android中获取图片的缩略图(解决OutOfMemoryError)内存溢出的Bug

    由于android获取图片过大是会出现内存溢出的Bug 07-02 05:10:13.792: E/AndroidRuntime(6016): java.lang.OutOfMemoryError 解 ...