题目描述

  一个平原上有\(n\)个城市,第\(i\)个城市在点\((\cos \frac{2i\pi}{n},\sin \frac{2i\pi}{n})\)上。

  每个城市和最近的两个城市有一条直线段的路。

  此外,还有\(n-3\)条路,这些路不会和原有的路重合,这些路之间也不会相交。

  通过每条道路均要花费\(1\)的时间。

  每次给你两个城市,问你从一个城市到另一个城市最快要多久。

  \(n\leq 100000\)

题解

  先把图画出来,容易发现这是一个平面图,且这个图的对偶图是一棵树,每个点的度数不超过\(3\)。

  那么我们可以对这棵树分治(点分治边分治都可以)。

  每次选择一条边,对于每个询问,这个询问的最短路径可以经过这条边的两个端点,也可以不经过。

  那么可以从这条边的两个端点开始BFS,并更新答案。

  对于一个询问,如果这个询问的两个点不在这条边的同一侧,就可以把这个询问扔掉了,否则递归下去处理。

  时间复杂度:\(O(n\log n)\)

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<ctime>
  6. #include<cstdlib>
  7. #include<utility>
  8. #include<vector>
  9. #include<queue>
  10. using namespace std;typedef long long ll;typedef pair<int,int> pii;void open(const char *s){
  11. #ifndef ONLINE_JUDGE
  12. char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
  13. #endif
  14. }int rd(){int s,c;while((c=getchar())<'0'||c>'9');s=c-'0';while((c=getchar())>='0'&&c<='9')s=s*10+c-'0';return s;}
  15. vector<int> g[100010];
  16. int e[100010][3];
  17. int qu[100010][3];
  18. int c[100010];
  19. int ti;
  20. int tot;
  21. int b[100010];
  22. queue<int> q;
  23. int num[100010];
  24. int ans[100010];
  25. int d[100010];
  26. void bfs(int x)
  27. {
  28. d[x]=0;
  29. q.push(x);
  30. ti++;
  31. b[x]=ti;
  32. while(!q.empty())
  33. {
  34. x=q.front();
  35. q.pop();
  36. for(auto v:g[x])
  37. if(c[v]==tot&&b[v]!=ti)
  38. {
  39. d[v]=d[x]+1;
  40. b[v]=ti;
  41. q.push(v);
  42. }
  43. }
  44. }
  45. int cnt;
  46. int dist(int l,int r)
  47. {
  48. if(r<l)
  49. r+=cnt;
  50. return r-l+1;
  51. }
  52. int belong(int l,int r,int x)
  53. {
  54. if(l>r)
  55. r+=cnt;
  56. if(x<l)
  57. x+=cnt;
  58. return x<=r;
  59. }
  60. int belong2(int l,int r,int x)
  61. {
  62. if(l>r)
  63. r+=cnt;
  64. if(x<=l)
  65. x+=cnt;
  66. return x<r;
  67. }
  68. void solve(vector<int> &id,vector<int> &qid)
  69. {
  70. if(!qid.size())
  71. return;
  72. if(id.size()<=1)
  73. return;
  74. tot++;
  75. cnt=0;
  76. for(auto v:id)
  77. {
  78. c[v]=tot;
  79. num[v]=++cnt;
  80. }
  81. int s=0x7fffffff,x1,x2;
  82. for(auto v1:id)
  83. for(auto v2:g[v1])
  84. if(c[v2]==tot)
  85. {
  86. int v=max(dist(num[v1],num[v2]),dist(num[v2],num[v1]));
  87. if(v<s)
  88. {
  89. s=v;
  90. x1=v1;
  91. x2=v2;
  92. }
  93. }
  94. bfs(x1);
  95. for(auto v:qid)
  96. ans[v]=min(ans[v],d[qu[v][1]]+d[qu[v][2]]);
  97. bfs(x2);
  98. for(auto v:qid)
  99. ans[v]=min(ans[v],d[qu[v][1]]+d[qu[v][2]]);
  100. if(id.size()<=3)
  101. return;
  102. vector<int> id1,id2,qid1,qid2;
  103. for(auto v:id)
  104. {
  105. if(belong(num[x1],num[x2],num[v]))
  106. id1.push_back(v);
  107. if(belong(num[x2],num[x1],num[v]))
  108. id2.push_back(v);
  109. }
  110. for(auto v:qid)
  111. {
  112. if(belong2(num[x1],num[x2],num[qu[v][1]])&&belong2(num[x1],num[x2],num[qu[v][2]]))
  113. qid1.push_back(v);
  114. if(belong2(num[x2],num[x1],num[qu[v][1]])&&belong2(num[x2],num[x1],num[qu[v][2]]))
  115. qid2.push_back(v);
  116. }
  117. solve(id1,qid1);
  118. solve(id2,qid2);
  119. }
  120. int n,m;
  121. int main()
  122. {
  123. open("b");
  124. scanf("%d",&n);
  125. int x,y;
  126. for(int i=1;i<=n-3;i++)
  127. {
  128. scanf("%d%d",&x,&y);
  129. x++;
  130. y++;
  131. g[x].push_back(y);
  132. g[y].push_back(x);
  133. e[i][1]=x;
  134. e[i][2]=y;
  135. }
  136. for(int i=1;i<=n;i++)
  137. {
  138. g[i].push_back(i%n+1);
  139. g[i%n+1].push_back(i);
  140. }
  141. vector<int> id,qid;
  142. for(int i=1;i<=n;i++)
  143. id.push_back(i);
  144. scanf("%d",&m);
  145. for(int i=1;i<=m;i++)
  146. {
  147. scanf("%d%d",&qu[i][1],&qu[i][2]);
  148. qu[i][1]++;
  149. qu[i][2]++;
  150. qid.push_back(i);
  151. if(qu[i][1]==qu[i][2])
  152. ans[i]=0;
  153. else
  154. ans[i]=0x7fffffff;
  155. }
  156. solve(id,qid);
  157. for(int i=1;i<=m;i++)
  158. printf("%d\n",ans[i]);
  159. return 0;
  160. }

【XSY2771】城市 分治的更多相关文章

  1. 【BZOJ2001】[HNOI2010]城市建设(CDQ分治,线段树分治)

    [BZOJ2001][HNOI2010]城市建设(CDQ分治,线段树分治) 题面 BZOJ 洛谷 题解 好神仙啊这题.原来想做一直不会做(然而YCB神仙早就切了),今天来怒写一发. 很明显这个玩意换种 ...

  2. BZOJ2001 [Hnoi2010]City 城市建设 CDQ分治

    2001: [Hnoi2010]City 城市建设 Time Limit: 20 Sec  Memory Limit: 162 MB Description PS国是一个拥有诸多城市的大国,国王Lou ...

  3. 【HNOI2010】城市建设(对时间分治 & Kruskal)

    Description \(n\) 个点 \(m\) 条边的带边权无向图.\(q\) 次操作,每次修改一条边的权值. 求每次修改后的最小生成树的边权和. Hint \(1\le n\le 2\time ...

  4. BZOJ2001 HNOI2010城市建设(线段树分治+LCT)

    一个很显然的思路是把边按时间段拆开线段树分治一下,用lct维护MST.理论上复杂度是O((M+Q)logNlogQ),实际常数爆炸T成狗.正解写不动了. #include<iostream> ...

  5. 【CDQ分治】[HNOI2010]城市建设

    题目链接 线段树分治+LCT只有80 然后就有了CDQ分治的做法 把不可能在生成树里的扔到后面 把一定在生成树里的扔到并查集里存起来 分治到l=r,修改边权,跑个kruskal就行了 由于要支持撤销, ...

  6. BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】

    题目链接 BZOJ2001 题解 CDQ分治神题... 难想难写.. 比较朴素的思想是对于每个询问都求一遍\(BST\),这样做显然会爆 考虑一下时间都浪费在了什么地方 我们每次求\(BST\)实际上 ...

  7. bzoj 2001 CITY 城市建设 cdq分治

    题目传送门 题解: 对整个修改的区间进行分治.对于当前修改区间来说,我们对整幅图中将要修改的边权都先改成-inf,跑一遍最小生成树,然后对于一条树边并且他的权值不为-inf,那么这条边一定就是树边了. ...

  8. P3206 [HNOI2010]城市建设 [线段树分治+LCT维护动态MST]

    Problem 这题呢 就边权会在某一时刻变掉-众所周知LCT不支持删边的qwq- 所以考虑线段树分治- 直接码一发 如果 R+1 这个时间修改 那就当做 [L,R] 插入了一条边- 然后删的边和加的 ...

  9. BZOJ 2001: [Hnoi2010]City 城市建设

    2001: [Hnoi2010]City 城市建设 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1132  Solved: 555[Submit][ ...

随机推荐

  1. 搜狐畅游一面(c++)

    上来是个小姐姐,有点懵.. 1.  介绍 2.  项目 3.  实习 4.  用的协议 tcp和udp的协议 5.  select 和epoll(忘了) 6. 数据库的隔离级别, 死锁, 怎么避免死锁 ...

  2. transfer.sh:通过命令行简单的创建文件分享

    简介 通过一个命令,就可以在终端上,将文件加密传输到远程服务器,提供对外文件共享的功能. transfer.sh这是一个我常用的.可以在终端上使用的文件共享服务,可以在某些方面替代sz或者scp命令. ...

  3. Python“Non-ASCII character 'xe5' in file”报错问题

    今天在编译一个Python程序的时候,一直出现“Non-ASCII character 'xe5' in file”报错问题 SyntaxError: Non-ASCII character '\xe ...

  4. 在做stark中一些反射的问题。

    hasattr(obj,name): 判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False.需要注意的是name要用括号括起来   1 ...

  5. Python之缩进块

    pycharm编辑器识别冒号,当换行后下一行默认是缩进块的位置:

  6. [转][mysql]创建函数失败(1418错误)mysql双主模式导致的问题

    https://blog.csdn.net/qq523786283/article/details/75102170

  7. Nginx三部曲(3)SSL

    我们将告诉你 Nginx 的运作模式.蕴含的概念,怎样通过调优 Nginx 来提高应用性能,或是如何设置它的启动和运行. 这个教程有三个部分: 基本概念 —— 这部分需要去了解 Nginx 的一些指令 ...

  8. laravel自定义门面

    https://learnku.com/articles/19195   关于laravel门面和服务提供者使用的一点见解,门面之词,不足之处,还请多多指教. 在laravel中,我们可能需要用到自己 ...

  9. Day 4-8 hashlib加密模块

    HASH Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射 ...

  10. java学习之—链表(3)

    /** * 使用链表实现队列 * Create by Administrator * 2018/6/19 0019 * 下午 4:37 **/ public class Link { public l ...