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了一次

  1. #pragma comment(linker, "/STACK:102400000,102400000")
  2. #include<iostream>
  3. #include<vector>
  4. #include<algorithm>
  5. #include<cstdio>
  6. #include<queue>
  7. #include<stack>
  8. #include<string>
  9. #include<map>
  10. #include<set>
  11. #include<cmath>
  12. #include<cassert>
  13. #include<cstring>
  14. #include<iomanip>
  15. using namespace std;
  16. #ifdef _WIN32
  17. #define i64 __int64
  18. #define out64 "%I64d\n"
  19. #define in64 "%I64d"
  20. #else
  21. #define i64 long long
  22. #define out64 "%lld\n"
  23. #define in64 "%lld"
  24. #endif
  25. /************ for topcoder by zz1215 *******************/
  26. #define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
  27. #define FOR(i,a,b) for( int i = (a) ; i <= (b) ; i ++)
  28. #define FF(i,a) for( int i = 0 ; i < (a) ; i ++)
  29. #define FFD(i,a,b) for( int i = (a) ; i >= (b) ; i --)
  30. #define S64(a) scanf(in64,&a)
  31. #define SS(a) scanf("%d",&a)
  32. #define LL(a) ((a)<<1)
  33. #define RR(a) (((a)<<1)+1)
  34. #define pb push_back
  35. #define pf push_front
  36. #define X first
  37. #define Y second
  38. #define CL(Q) while(!Q.empty())Q.pop()
  39. #define MM(name,what) memset(name,what,sizeof(name))
  40. #define MC(a,b) memcpy(a,b,sizeof(b))
  41. #define MAX(a,b) ((a)>(b)?
  42.  
  43. (a):(b))
  44. #define MIN(a,b) ((a)<(b)?(a):(b))
  45. #define read freopen("out.txt","r",stdin)
  46. #define write freopen("out2.txt","w",stdout)
  47.  
  48. const int inf = 0x3f3f3f3f;
  49. const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
  50. const double oo = 10e9;
  51. const double eps = 10e-9;
  52. const double pi = acos(-1.0);
  53. const int maxn = 211111;
  54.  
  55. struct Node{
  56. int now;
  57. int to;
  58. int h;
  59. bool operator < (const Node & cmp) const{
  60. return h>cmp.h;
  61. }
  62. }node;
  63.  
  64. int n;
  65. vector<Node>g[maxn];
  66. int dfv[maxn];
  67. int dfn[maxn];
  68. int t[maxn];
  69. int h[maxn];
  70.  
  71. int df;
  72. vector<int>s;
  73. vector<int>si;
  74. bool vis[maxn];
  75. vector<int>line;
  76. int a[maxn];
  77. int ax[maxn][20];
  78. int dx[maxn][20];
  79. int lg2[maxn];
  80. bool isline[maxn];
  81.  
  82. void dfs(){
  83. for (int i = 1; i <= n; i++){
  84. vis[i] = false;
  85. }
  86. df = 1;
  87. s.clear();
  88. si.clear();
  89. s.push_back(1);
  90. si.push_back(0);
  91. vis[1] = true;
  92. int now, to, id;
  93. while (!s.empty()){
  94. now = s.back();
  95. id = si.back();
  96. if (id < g[now].size()){
  97. to = g[now][id].to;
  98. si.back()++;
  99. if (!vis[to]){
  100. vis[to] = true;
  101. t[to] = now;
  102. s.push_back(to);
  103. si.push_back(0);
  104. }
  105. }
  106. else{
  107. dfv[df] = s.back();
  108. dfn[s.back()] = df++;
  109. s.pop_back();
  110. si.pop_back();
  111. }
  112. }
  113. }
  114.  
  115. int find_len(int now){
  116. if (g[now].size() >= 2){
  117. return g[now][0].h + g[now][1].h;
  118. }
  119. else if (g[now].size() == 1){
  120. return g[now][0].h;
  121. }
  122. else{
  123. return 0;
  124. }
  125. }
  126.  
  127. void get_line(int now){
  128. if (g[now].size() >= 2){
  129. int t1 = g[now][0].to;
  130. int t2 = g[now][1].to;
  131. isline[now] = true;
  132. while (true){
  133. isline[t1] = true;
  134. line.push_back(t1);
  135. if (g[t1].size() > 0){
  136. t1 = g[t1][0].to;
  137. }
  138. else{
  139. break;
  140. }
  141. }
  142.  
  143. reverse(line.begin(), line.end());
  144. line.push_back(now);
  145. while (true){
  146. isline[t2] = true;
  147. line.push_back(t2);
  148. if (g[t2].size() > 0){
  149. t2 = g[t2][0].to;
  150. }
  151. else{
  152. break;
  153. }
  154. }
  155. }
  156. else if(g[now].size() ==1){
  157. while (true){
  158. isline[now] = true;
  159. line.push_back(now);
  160. if (g[now].size() > 0){
  161. now = g[now][0].to;
  162. }
  163. else{
  164. break;
  165. }
  166. }
  167. }
  168. }
  169.  
  170. int max_way(int now){
  171. int to;
  172. int re = 0;
  173. for (int i = 0; i < g[now].size(); i++){
  174. to = g[now][i].to;
  175. if (!isline[to]){
  176. re = max(re, g[now][i].h);
  177. }
  178. }
  179. return re;
  180. }
  181.  
  182. void sparse_table(){
  183. for (int i = 0; i < line.size(); i++){
  184. ax[i][0] = a[i]+i;
  185. dx[i][0] = a[i]+(int)line.size()-1-i;
  186. }
  187. for (int step = 1; (1 << step) < line.size(); step++){
  188. for (int i = 0; i < line.size(); i++){
  189. ax[i][step] = ax[i][step - 1];
  190. dx[i][step] = dx[i][step - 1];
  191. if (i + (1 << (step - 1)) < line.size()){
  192. ax[i][step] = max(ax[i][step], ax[i + (1 << (step - 1))][step - 1]);
  193. dx[i][step] = max(dx[i][step], dx[i + (1 << (step - 1))][step - 1]);
  194. }
  195. }
  196. }
  197. }
  198.  
  199. int max_a(int l, int r){
  200. return max(ax[l][lg2[r - l + 1]], ax[r - (1 << lg2[r - l + 1]) + 1][lg2[r - l + 1]]);
  201. }
  202.  
  203. int max_d(int l, int r){
  204. return max(dx[l][lg2[r - l + 1]], dx[r - (1 << lg2[r - l + 1]) + 1][lg2[r - l + 1]]);
  205. }
  206.  
  207. int find(int l, int r){
  208. int mid = (r + l) / 2;
  209. return max(max_a(l, mid) - l, max_d(mid+1,r)-( (int)line.size()-1-r ) );
  210. }
  211.  
  212. int back[maxn];
  213.  
  214. void find_back(){
  215. for (int i = 1; i <= n; i++){
  216. back[i] = 0;
  217. }
  218. queue<int>q;
  219. q.push(1);
  220. int now, to,fa,temp;
  221. while (!q.empty()){
  222. now = q.front();
  223. q.pop();
  224. if (t[now]){
  225. fa = t[now];
  226. back[now] = 1 + back[fa];
  227. temp = 0;
  228. if (g[fa][0].to == now){
  229. if (g[fa].size() >= 2){
  230. temp = g[fa][1].h+1;
  231. }
  232. }
  233. else{
  234. temp = g[fa][0].h;
  235. }
  236. back[now] = max(back[now], temp);
  237. }
  238. for (int i = 0; i < g[now].size(); i++){
  239. q.push(g[now][i].to);
  240. }
  241. }
  242. }
  243.  
  244. void start(){
  245. dfs();
  246. for (int i = 1; i <= n; i++){
  247. h[i] = 0;
  248. }
  249.  
  250. vector<Node>gg;
  251. int now, to;
  252. for (now = 1; now <= n; now++){
  253. gg.clear();
  254. for (int i = 0; i < g[now].size(); i++){
  255. to = g[now][i].to;
  256. if (to != t[now]){
  257. gg.push_back(g[now][i]);
  258. }
  259. }
  260. g[now] = gg;
  261. }
  262.  
  263. for (int x = 1; x < df; x++){
  264. now = dfv[x];
  265. for (int i = 0; i < g[now].size(); i++){
  266. to = g[now][i].to;
  267. h[now] = max(h[now], h[to] + 1);
  268. }
  269. }
  270.  
  271. for (now = 1; now <= n; now++){
  272. for (int i = 0; i < g[now].size(); i++){
  273. to = g[now][i].to;
  274. g[now][i].h = h[to] + 1;
  275. }
  276. }
  277.  
  278. for (now = 1; now <= n; now++){
  279. sort(g[now].begin(), g[now].end());
  280. }
  281.  
  282. int id;
  283. int len = -1;
  284. int temp;
  285. for (now = 1; now <= n; now++){
  286. temp = find_len(now);
  287. if (temp > len){
  288. len = temp;
  289. id = now;
  290. }
  291. }
  292.  
  293. for (int i = 1; i <= n; i++){
  294. isline[i] = false;
  295. }
  296. line.clear();
  297. get_line(id);
  298.  
  299. find_back();
  300.  
  301. for (int i = 0; i < line.size(); i++){
  302. a[i] = max_way(line[i]);
  303. if (line[i] == id){
  304. a[i] = max(a[i], back[id]);
  305. }
  306. }
  307.  
  308. sparse_table();
  309.  
  310. int ans=inf;
  311. int left;
  312. int right;
  313. int l, r;
  314. for (int lend = 0; lend < line.size(); lend++){
  315. l = lend;
  316. r = line.size() - 1;
  317. while (l + 2 < r){
  318. int mid = (l + r) / 2;
  319. if (find(lend, mid) > (int)line.size() - 1 - mid){
  320. r = mid;
  321. }
  322. else{
  323. l = mid;
  324. }
  325.  
  326. }
  327. for (int x = l; x <= r; x++){
  328. temp = max(find(lend, x), (int)line.size() - 1 - x);
  329. temp = max(temp, lend);
  330. if (temp < ans){
  331. ans = temp;
  332. left = lend;
  333. right = x;
  334. }
  335. }
  336. }
  337. cout << ans << " " << line[left] << " " << line[right] << endl;
  338. }
  339.  
  340. int main(){
  341. for (int i = 0; i < 20; i++){
  342. if ((1 << i) < maxn){
  343. lg2[1 << i] = i;
  344. }
  345. }
  346. for (int i = 3; i < maxn; i++){
  347. if (!lg2[i]){
  348. lg2[i] = lg2[i - 1];
  349. }
  350. }
  351.  
  352. int T;
  353. cin >> T;
  354. while (T--){
  355. cin >> n;
  356. for (int i = 1; i <= n; i++){
  357. g[i].clear();
  358. }
  359. node.h = 0;
  360. for (int i = 1; i <= n - 1; i++){
  361. // cin >> node.now >> node.to;
  362. SS(node.now); SS(node.to);
  363. g[node.now].push_back(node);
  364. swap(node.now, node.to);
  365. g[node.now].push_back(node);
  366. }
  367. start();
  368. }
  369. return 0;
  370. }

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

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. HTML与XML关系分析

    本来这篇是为CSS准备的,但看到视频中CSS和HTML.XML都有关系,即,都是设置他们的样式.而XML和HTML的格式看着也有些类似,就不得不分析一下二者之间的关系了. 要想分析事物关系,要先弄清他 ...

  2. POJ 3652 &amp; ZOJ 2934 &amp; HDU 2721 Persistent Bits(数学 元)

    主题链接: PKU:http://poj.org/problem?id=3652 ZJU:http://acm.zju.edu.cn/onlinejudge/showProblem.do? probl ...

  3. JDBC数据库连接

    JDBC是什么? Java Data Base Connectivity JDBC是: 以统一方式訪问数据库的API,能够訪问不论什么类型表列数据.特别是存储在关系数据中的数据.JDBC代表Java数 ...

  4. ajax相关体会

    参考原文: 例子:http://blog.csdn.net/beijiguangyong/article/details/7725596 原理讲解:http://www.cnblogs.com/min ...

  5. hdu 4007 Dave (2011年大连ACM网络赛)

    题意:给定正方形的边长 r ,在平面内寻找正方形可以圈住的点的最大的个数. 分析:先对点排序,然后固定一条边,再平移另一条垂直边,得到点的个数,最后比较大小即可. 注意:不包含正方形倾斜的情况! // ...

  6. OpenCV 编程简单介绍(矩阵/图像/视频的基本读写操作)

    PS. 因为csdn博客文章长度有限制,本文有部分内容被截掉了.在OpenCV中文站点的wiki上有可读性更好.而且是完整的版本号,欢迎浏览. OpenCV Wiki :<OpenCV 编程简单 ...

  7. 关于oracle的备份 导入

    ****假设要保存为bat文件.最好用汉字 导入: imp clsoftoa/clsoftoa@orcl124  --要导入的数据库的 username/password@数据库名 fromuser= ...

  8. Install Linux Kernel - AT91SAM9260EK

    两.AT91SAM9260EK 2.1下载 介绍页: http://www.at91.com/linux4sam/bin/view/Linux4SAM/LegacyLinuxKernel 下载页: a ...

  9. sql小技巧 group by datetime类型字段,只取其中的日期部分

    工作中经常会遇到,要在sql中查询报表,查询结果要求按照日期来罗列, 或按照天, 或按照月,年. 这个时候我们经常会苦恼,datetime是精确到毫秒的,如果单纯的group by datetime就 ...

  10. 王立平--Program Files (x86)

    window7根据系统.program files(x86) 它是应用程序目录,在64下位系统.为了更好的相容性32位程序,在一些安装32位程序(请注意,有些节目自己是32位),将默认被安装progr ...