热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【BZOJ1969】【AHOI2005】LANE航线规划【离线、hash、并查集、树链剖分、线段树】

Description星际空间站的SamuelII巨型计算机经过长期探测,已经锁定了Samuel星系中许多星球的空间坐标,并对这些星球从1开始编号1、

Description

星际空间站的Samuel II巨型计算机经过长期探测,已经锁定了Samuel星系中许多星球的空间坐标,并对这些星球从1开始编号1、2、3……。 一些先遣飞船已经出发,在星球之间开辟探险航线。 探险航线是双向的,例如从1号星球到3号星球开辟探险航线,那么从3号星球到1号星球也可以使用这条航线。 例如下图所示: 在5个星球之间,有5条探险航线。 A、B两星球之间,如果某条航线不存在,就无法从A星球抵达B星球,我们则称这条航线为关键航线。
这里写图片描述
显然上图中,1号与5号星球之间的关键航线有1条:即为4-5航线。 然而,在宇宙中一些未知的磁暴和行星的冲撞,使得已有的某些航线被破坏,随着越来越多的航线被破坏,探险飞船又不能及时回复这些航线,可见两个星球之间的关键航线会越来越多。 假设在上图中,航线4-2(从4号星球到2号星球)被破坏。此时,1号与5号星球之间的关键航线就有3条:1-3,3-4,4-5。 小联的任务是,不断关注航线被破坏的情况,并随时给出两个星球之间的关键航线数目。现在请你帮助完成。


Input

第一行有两个整数N,M。表示有N个星球(1

Output

对每个C为1的询问,输出一行一个整数表示关键航线数目。 注意:我们保证无论航线如何被破坏,任意时刻任意两个星球都能够相互到达。在整个数据中,任意两个星球之间最多只可能存在一条直接的航线。


题解

  感觉这题非常好啊。

  一开始非常zz地在不是很会写,一直在思考并查集怎么做分离,不过一看到题解,就感受到了树链剖分的妙处啊。
  
  我们假设一开始只有一棵树,那么显然每条边都是关键路线。然后我们考虑加上一条边时,一定会形成一个环,这样这个环上的每条边都不是关键路径了。因为是统计两个点之间的关键路径数量,所以直接用0、1来表示是否为关键路径,最后只需统计路径和即可。到这里,可以显然地看出树链剖分了。用线段树在链上做区间覆盖和区间求和即可。
  
  不过我们怎么变成上述的模型呢?只需离线处理,先将所有的边都读入,不过怎么记录被删除的边呢?这里又可以使用hash法,将边hash成数字(通过所连接的点随便搞搞出一个独特的值),在map的帮助下表示这条边有没有被摧毁。所以全部读入完后我们还剩一些边,用并查集来建树。然后反向操作一开始记录的读入,往树上加边就是一个区间覆盖。
  
  这样,这题的思路就非常地显然了。


代码

#include
#include
#include
#include#define N 30010
#define M 100010
#define C 40010
using namespace std;map <int,bool> hash;
int f[N];
struct node1{int x,y;}edge[M],not_tree[M];
struct node2{int to,next;}e[M*2];
int head[N],tot,t,tim,n;
int dep[N],fa[N],top[N],son[N],size[N],tid[N];
int x[C],y[C],opt[C],ans[C];void init() {tot &#61; 0;//the number of ok edget &#61; 0; tim &#61; 0;memset(son,-1,sizeof(son));memset(head,0,sizeof(head));
}int find(int x) { return x &#61;&#61; f[x] ? x : f[x] &#61; find(f[x]); }void add_edge(int from,int to) {e[&#43;&#43;tot].next &#61; head[from]; head[from] &#61; tot; e[tot].to &#61; to;
}void dfs1(int v,int pa,int d)
{dep[v] &#61; d; fa[v] &#61; pa; size[v] &#61; 1;for(int i &#61; head[v];i;i&#61;e[i].next)if(e[i].to !&#61; pa) {dfs1(e[i].to,v,d&#43;1);size[v] &#43;&#61; size[e[i].to];if(son[v] &#61;&#61; -1 || size[e[i].to] > size[son[v]])son[v] &#61; e[i].to;}
}void dfs2(int v,int tp)
{top[v] &#61; tp; tid[v] &#61; &#43;&#43;tim;if(son[v] &#61;&#61; -1) return;dfs2(son[v],tp);for(int i &#61; head[v];i;i&#61;e[i].next) {if(e[i].to !&#61; son[v] && e[i].to !&#61; fa[v])dfs2(e[i].to,e[i].to);}
}#define lson o <<1
#define rson o <<1 | 1
int sum[N <<2],setv[N <<2];void build(int o,int l,int r)
{setv[o] &#61; -1;if(l &#61;&#61; r) {sum[o] &#61; 1; if(l &#61;&#61; 1) sum[o] &#61; 0; return;}int mid &#61; (l&#43;r)>>1;build(lson,l,mid); build(rson,mid&#43;1,r);sum[o] &#61; sum[lson] &#43; sum[rson];
}void pushdown(int o)
{if(setv[o] !&#61; -1) {setv[lson] &#61; setv[rson] &#61; 0;sum[lson] &#61; sum[rson] &#61; 0;setv[o] &#61; -1;}
}void update(int o,int l,int r,int ll,int rr)
{if(ll <&#61; l && rr >&#61; r) {sum[o] &#61; setv[o] &#61; 0;return;}pushdown(o);int mid &#61; (l&#43;r)>>1;if(ll <&#61; mid) update(lson,l,mid,ll,rr);if(rr > mid) update(rson,mid&#43;1,r,ll,rr);sum[o] &#61; sum[lson] &#43; sum[rson];
}void change(int x,int y)
{while(top[x] !&#61; top[y]) {if(dep[top[x]] 1,1,n,tid[top[x]],tid[x]);x &#61; fa[top[x]];}if(dep[x] > dep[y]) swap(x,y);update(1,1,n,tid[x]&#43;1,tid[y]);
}int query(int o,int l,int r,int ll,int rr)
{if(ll <&#61; l && rr >&#61; r) return sum[o];int mid &#61; (l&#43;r)>>1,ans &#61; 0;pushdown(o);if(ll <&#61; mid) ans &#43;&#61; query(lson,l,mid,ll,rr);if(rr > mid) ans &#43;&#61; query(rson,mid&#43;1,r,ll,rr);return ans;
}int ask(int x,int y)
{int ans &#61; 0;while(top[x] !&#61; top[y]) {if(dep[top[x]] 1,1,n,tid[top[x]],tid[x]);x &#61; fa[top[x]];}if(dep[x] > dep[y]) swap(x,y);ans &#43;&#61; query(1,1,n,tid[x]&#43;1,tid[y]);return ans;
}int main()
{int m,q;scanf("%d%d",&n,&m);for(int i &#61; 1;i <&#61; m;i&#43;&#43;) {scanf("%d%d",&edge[i].x,&edge[i].y);if(edge[i].x > edge[i].y) swap(edge[i].x,edge[i].y);}q &#61; 0;while(scanf("%d",&opt[&#43;&#43;q]) && opt[q] !&#61; -1) {scanf("%d%d",&x[q],&y[q]);if(x[q] > y[q]) swap(x[q],y[q]);if(opt[q] &#61;&#61; 0) hash[ (x[q]-1)*n&#43;y[q] ] &#61; true;}for(int i &#61; 1;i <&#61; n;i&#43;&#43;) f[i] &#61; i;init();for(int i &#61; 1;i <&#61; m;i&#43;&#43;){int now &#61; (edge[i].x-1)*n&#43;edge[i].y;if(hash[now]) continue;int f1 &#61; find(edge[i].x),f2 &#61; find(edge[i].y);if(f1 !&#61; f2) {add_edge(edge[i].x,edge[i].y); add_edge(edge[i].y,edge[i].x);f[f1] &#61; f2;}else {not_tree[&#43;&#43;t].x &#61; edge[i].x;not_tree[t].y &#61; edge[i].y;}}dfs1(1,0,0); dfs2(1,1);build(1,1,n);for(int i &#61; 1;i <&#61; t;i&#43;&#43;) change(not_tree[i].x,not_tree[i].y);for(int i &#61; q-1;i >&#61; 1;i--)if(opt[i] &#61;&#61; 0) change(x[i],y[i]); else ans[i] &#61; ask(x[i],y[i]);for(int i &#61; 1;i if(opt[i]) printf("%d\n",ans[i]);return 0;
}

推荐阅读
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
author-avatar
小石头
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有