题面

在Byteland一共有n 个城市,编号依次为1 到n,它们之间计划修建m条双向道路,其中修建第i 条道路的费用为ci。

Byteasar作为Byteland 公路建设项目的总工程师,他决定选定一个区间[l, r],仅使用编号在该区间内的道路。他希望选择一些道路去修建,使得连通块的个数尽量少,同时,他不喜欢修建多余的道路,因此每个连通块都可以看成一棵树的结构。

为了选出最佳的区间,Byteasar 会不断选择q 个区间,请写一个程序,帮助Byteasar 计算每个区间内修建公路的最小总费用。

30~60

30分暴力;

60分,考虑到由于边的权值随编号递增,所以对于一个询问区间\([l,r]\),显然能往前取,尽量往前取。

所以,我们把边从大到小加入,对树的结构每次加边后暴力重构,方便加边时LCA。

然后对于一个区间\([l,r]\),就要把\([l,m]\)的边,然后我用数据结构找生成树中编号小于\(r\)的权值和。

100

开棵线段树,树上每个结点表示,使用区间内的边生成的mst,最多存储\(O(n)\)条边,空间就有\(O(n*m*log_m)\)

然后我对于每个询问就只需\(O(log_m*n)\)的时间。

总的时间复杂度为\(O(log_m*n*q)\)。

为什么可以用线段树

前提条件:离线;

关键条件:区间合并只需\(O(n)\)。

Code

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<queue>
  7. #define ll long long
  8. #define fo(i,x,y) for(int i=x;i<=y;i++)
  9. #define fd(i,x,y) for(int i=x;i>=y;i--)
  10. using namespace std;
  11. const char* fin="highway.in";
  12. const char* fout="highway.out";
  13. const int maxn=107,maxm=100007,maxt=maxm*4;
  14. int n,m,q,t[maxn*2];
  15. struct line{
  16. int x,y,z;
  17. }a[maxm];
  18. struct node{
  19. node(){r[0]=0;}
  20. int r[maxn];
  21. }c[maxt],ans,tmp;
  22. struct bitch{
  23. int data[maxm],az[maxm],id;
  24. bitch(){memset(az,0,sizeof az);id=0;}
  25. void init(){id++;}
  26. int& operator [](const int &v){
  27. if (az[v]<id) az[v]=id,data[v]=0;
  28. return data[v];
  29. }
  30. }dad;
  31. int getdad(int v){return dad[v]==0?v:dad[v]=getdad(dad[v]);}
  32. void merge(node &v,const node &b,const node &c){
  33. t[0]=0;
  34. int i=1,j=1;
  35. while (i<=b.r[0] && j<=c.r[0])
  36. if (a[b.r[i]].z<a[c.r[j]].z) t[++t[0]]=b.r[i++];
  37. else t[++t[0]]=c.r[j++];
  38. while (i<=b.r[0]) t[++t[0]]=b.r[i++];
  39. while (j<=c.r[0]) t[++t[0]]=c.r[j++];
  40. v.r[0]=0;
  41. dad.init();
  42. fo(i,1,t[0]){
  43. int j=getdad(a[t[i]].x),k=getdad(a[t[i]].y);
  44. if (j!=k){
  45. dad[j]=k;
  46. v.r[++v.r[0]]=t[i];
  47. }
  48. }
  49. }
  50. void plant(int l,int r,int t){
  51. int mid=(l+r)/2;
  52. if (l==r){
  53. c[t].r[0]=1;
  54. c[t].r[1]=l;
  55. return;
  56. }
  57. plant(l,mid,t*2);
  58. plant(mid+1,r,t*2+1);
  59. merge(c[t],c[t*2],c[t*2+1]);
  60. }
  61. node query(int l,int r,int t,int v1,int v2){
  62. int mid=(l+r)/2;
  63. if (l>v2 || r<v1) return node();
  64. if (l>=v1 && r<=v2) return c[t];
  65. merge(tmp,query(l,mid,t*2,v1,v2),query(mid+1,r,t*2+1,v1,v2));
  66. return tmp;
  67. }
  68. int main(){
  69. freopen(fin,"r",stdin);
  70. freopen(fout,"w",stdout);
  71. scanf("%d%d%d",&n,&m,&q);
  72. fo(i,1,m){
  73. scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
  74. }
  75. plant(1,m,1);
  76. fo(i,1,q){
  77. int l,r;
  78. scanf("%d%d",&l,&r);
  79. ans=query(1,m,1,l,r);
  80. int Ans=0;
  81. fo(j,1,ans.r[0]) Ans+=a[ans.r[j]].z;
  82. printf("%d\n",Ans);
  83. }
  84. return 0;
  85. }

【JZOJ5060】【GDOI2017第二轮模拟day1】公路建设 线段树+最小生成树的更多相关文章

  1. GDOI2017第二轮模拟day1 总结

    平民比赛 这场比赛的暴力分非常友好. 但是我并没有拿到全部的暴力分. 1(暴力分\(60/100\)) 暂时我可以拿的暴力分为\(30/100\),直接mst模拟即可. 然而当时打了个辣鸡莫队,结果爆 ...

  2. 【JZOJ5064】【GDOI2017第二轮模拟day2】友好城市 Kosarajo算法+bitset+ST表+分块

    题面 在Byteland 一共有n 座城市,编号依次为1 到n,这些城市之间通过m 条单向公路连接. 对于两座不同的城市a 和b,如果a 能通过这些单向道路直接或间接到达b,且b 也能如此到达a,那么 ...

  3. bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树

    [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 93  Solved: 53[Submit][Status][ ...

  4. [jzoj5073 GDOI2017第二轮模拟] 影魔

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...

  5. BZOJ 1920 Luogu P4217 [CTSC2010]产品销售 (模拟费用流、线段树)

    题目链接 (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=1920 (luogu) https://www.luogu.org/prob ...

  6. BZOJ 5326 [JSOI2017]博弈 (模拟费用流、线段树)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5326 题解 终于成为第8个A掉这题的人--orz tzw神仙早我6小时 本以为这东西常数 ...

  7. Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]

    洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...

  8. 【10.6校内测试】【小模拟】【hash+线段树维护覆盖序列】

    一开始看到题就果断跳到T2了!!没想到T2才是个大坑,浪费了两个小时QAQ!! 就是一道小模拟,它怎么说就怎么走就好了! 为什么要用这么多感叹号!!因为统计答案要边走边统计!!如果每个数据都扫一遍20 ...

  9. Contest Hunter 模拟赛09 A [线段树维护斜率]

    题面 传送门 思路 首先看看我们到底要干什么:有$1e6$次询问,遍历$i$,每次要求一个形如$b_i \ast a_j - a_i \ast b_j$的东西的最大值 考虑如果一个$j$的决策在当前的 ...

随机推荐

  1. Struts2入门问题

    一 使用Struts 2 开发程序的基本步骤 加载Struts2 类库 配置web.xml文件 开发视图层页面 开发控制层Action 配置struts.xml文件 部署.运行项目 第一步先导架包:在 ...

  2. NFS和mount常用参数详解 本文目录

    NFS和mount常用参数详解   本文目录 NFS权限参数配置 mount挂载参数 原始驱动程序的挂载选项. 新驱动程序的挂载选项. 怎样改变已经挂载的NTFS卷的权限? 怎样自动挂载一个NTFS卷 ...

  3. Ajax 导出Excel 方式

    1.使用iframe 加载 使用get方式 <iframe id="comdownshow" height="0" width="0" ...

  4. leyou_07_对数据的操作

    1.目标在数据库的两张表中拿到以下数据,并完成状态.搜索和分页功能 实体类Spu(页面需要的数据) 实体类Category(页面需要的数据) name:商品分类 2.分析: 返回的数据在两个实体类中, ...

  5. python 日记 day4。

    1.为何数据要分类 数据是用来表示状态的,不同的状态应该用不同类型的数据来表示. 2.数据类型 数字 字符串 列表 元组 字典 集合 列表:列表相比于字符串,不仅可以储存不同的数据类型,而且可以储存大 ...

  6. javascript中json对象与json字符串

    var data = "{'name':'张山','age':20}"; //转换字符串为json对象: var jsondata = JSON.parse(data); //转换 ...

  7. AppbarLayout的简单用法

    在许多App中看到, toolbar有收缩和扩展的效果, 例如:   appbar.gif 要实现这样的效果, 需要用到: CoordinatorLayout和AppbarLayout的配合, 以及实 ...

  8. Hibernate命名策略

    hibernate的命名策略,可以减少对数据库标识符命名的维护,进一步减少这部份命名的重复性代码量,以提高维护. hibernate的命名方式,有两类,一类是显式命名,一类是隐式命名. 显式命名:在映 ...

  9. 2019牛客暑期多校赛(第一场) A Equivalent Prefixes(单调栈)

    传送门:https://ac.nowcoder.com/acm/contest/881/A 题意:给定两个数组a和b,求最大的p,满足在区间 [1,p] 中任何区间的两个数组的最小值的下标都相等. 思 ...

  10. 【DM642】H.264源代码在DM642上的移植

    TI公司提供了用于C语言开发的CCS(Code Composer Studio),该平台包括了优化的ANSI编译器,使之可以使用C语言开发DSP程序.这种方法不仅使DSP开发的速度大大加快,而且DSP ...