【LOJ#3145】[APIO2019]桥梁(分块,并查集)
【LOJ#3145】[APIO2019]桥梁(分块,并查集)
题面
题解
因为某个\(\text{subtask}\)没判\(n=1\)的情况导致我自闭了很久的题目。。。
如果没有修改操作,可以克鲁斯卡尔重构树在线处理。或者按照边权排序离线并查集处理。
现在有修改操作,于是我们来分块。
我们对于操作分块,每\(B\)个操作作为一组处理。不同组之间显然影响不大。
所以我们只需要处理同一组的就好了。
把边分成两类,一类是不会被修改的,这些边直接排序做前面的并查集就好了,这部分复杂度是\(O(m\frac{n}{B})\)的。另外一类是会被修改的,对于每次询问,我们暴力扫所有会被修改的边,看看是否可以加入进来,因此块内的修改边数不会超过\(B\),所以这一部分是\(O(\frac{n}{B}B^2)=O(nB)\)的,但是还要支持并查集的撤销,所以多一个\(log\),所以是\(O(nBlogn)\)的。
均摊一下取\(B=\sqrt {m logn}\)???
注意几个细节,前半部分那里分析复杂度的时候没有带\(log\),所以用归并排序。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
const int BLK=500;
struct Edge{int u,v,w,i;}e[MAX],E[MAX],tmpE[MAX];
bool operator<(Edge a,Edge b){if(a.w!=b.w)return a.w>b.w;return a.i<b.i;}
bool cmpi(Edge a,Edge b){return a.i<b.i;}
int n,m,Q,ans[MAX];
int f[MAX],sz[MAX];
int getf(int x){return x==f[x]?x:getf(f[x]);}
struct dsuopt{int u,v;}St[MAX];int top;
void Merge(int u,int v)
{
u=getf(u);v=getf(v);
if(u==v)return;
if(sz[u]<sz[v])swap(u,v);
f[v]=u;sz[u]+=sz[v];
St[++top]=(dsuopt){u,v};
}
void Cancel(){int u=St[top].u,v=St[top].v;--top;f[v]=v;sz[u]-=sz[v];}
struct Opt{int id,t,b,r;}q[MAX],tmp1[MAX],tmp2[MAX];int tot,t1,t2;
bool cmpb(Opt a,Opt b){return a.b>b.b;}
int vis[MAX],id[MAX],d[MAX];
void Work()
{
for(int i=1;i<=m;++i)vis[i]=false;
for(int i=1;i<=n;++i)f[i]=i,sz[i]=1;
t1=t2=top=0;
for(int i=1;i<=tot;++i)
if(q[i].t==1)++t1,vis[q[i].b]=true,tmp1[t1]=q[i];
else tmp2[++t2]=q[i];
sort(&tmp2[1],&tmp2[t2+1],cmpb);
for(int i=1;i<=m;++i)id[e[i].i]=i;
for(int i=1,p=1;i<=t2;++i)
{
while(p<=m&&e[p].w>=tmp2[i].b)
{
if(!vis[e[p].i])Merge(e[p].u,e[p].v);
++p;
}
int ltop=top;
for(int j=1;j<=t1;++j)d[tmp1[j].b]=e[id[tmp1[j].b]].w;
for(int j=1;j<=t1;++j)
if(tmp1[j].id<tmp2[i].id)
d[tmp1[j].b]=tmp1[j].r;
for(int j=1;j<=t1;++j)
if(d[tmp1[j].b]>=tmp2[i].b)
Merge(e[id[tmp1[j].b]].u,e[id[tmp1[j].b]].v);
ans[tmp2[i].id]=sz[getf(tmp2[i].r)];
while(top>ltop)Cancel();
}
for(int i=1;i<=t1;++i)e[id[tmp1[i].b]].w=tmp1[i].r;
t1=t2=0;
for(int i=1;i<=m;++i)
if(vis[e[i].i])E[++t1]=e[i];
else e[++t2]=e[i];
sort(&E[1],&E[t1+1]);
merge(&e[1],&e[t2+1],&E[1],&E[t1+1],&tmpE[1]);
for(int i=1;i<=m;++i)e[i]=tmpE[i];
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;++i)e[i].u=read(),e[i].v=read(),e[i].w=read(),e[i].i=i;
sort(&e[1],&e[m+1]);
Q=read();
for(int i=1;i<=Q;++i)
{
int t=read(),b=read(),r=read();if(t==2)swap(b,r);
q[++tot]=(Opt){i,t,b,r};
if(tot==BLK)Work(),tot=0;
}
if(tot)Work();
for(int i=1;i<=Q;++i)if(ans[i])printf("%d\n",ans[i]);
return 0;
}
【LOJ#3145】[APIO2019]桥梁(分块,并查集)的更多相关文章
- P5443 [APIO2019]桥梁 [分块+并查集]
分块+并查集,大板子,没了. 并查集不路径压缩,可撤销,然后暴力删除 这样对于每个块都是独立的,所以直接搞就行了. 然后块内修改操作搞掉,就是单独的了 // powered by c++11 // b ...
- [APIO2019] [LOJ 3145] 桥梁(分块+并查集)(有详细注释)
[APIO2019] [LOJ 3145] 桥梁(分块+并查集)(有详细注释) 题面 略 分析 考试的时候就感觉子任务4是突破口,结果却写了个Kruskal重构树,然后一直想怎么在线用数据结构维护 实 ...
- 洛谷P3247 最小公倍数 [HNOI2016] 分块+并查集
正解:分块+并查集 解题报告: 传送门! 真的好神仙昂QAQ,,,完全想不出来,,,还是太菜了QAQ 首先还是要说下,这题可以用K-D Tree乱搞过去(数据结构是个好东西昂,,,要多学学QAQ),但 ...
- [BZOJ4537][HNOI2016]最小公倍数(分块+并查集)
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1687 Solved: 607[Submit][Stat ...
- BZOJ4320 ShangHai2006 Homework(分块+并查集)
考虑根号分块.对于<√3e5的模数,每加入一个数就暴力更新最小值:对于>√3e5的模数,由于最多被分成√3e5块,查询时对每一块找最小值,这用一些正常的DS显然可以做到log,但不太跑得过 ...
- HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)
题目链接 2017 CCPC Hangzhou Problem H 思路:对树进行分块.把第一棵树分成$\sqrt{n}$块,第二棵树也分成$\sqrt{n}$块. 分块的时候满足每个块是一个 ...
- bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集
题目大意: 给定一张n个点m条边的无向图,每条边有两种权.每次询问某两个点之间是否存在一条路径上的边的两种权的最大值分别等于给定值. n,q <= 50000. m <= 100000 题 ...
- 失控的未来交通工具 (LOJ 508,带权并查集,数论)
LOJ 508 失控的未来交通工具 (带权并查集 + 数论) $ solution: $ 很综合的一道难题.看了让人不知所措,数据范围又大,题目描述又不清晰.只能说明这道题有很多性质,或者很多优化. ...
- Codeforces 506D Mr. Kitayuta's Colorful Graph(分块 + 并查集)
题目链接 Mr. Kitayuta's Colorful Graph 把每种颜色分开来考虑. 所有的颜色分为两种:涉及的点的个数 $> \sqrt{n}$ 涉及的点的个数 $<= ...
- 洛谷P4004 Hello world!(分块+并查集)
传送门 虽然洛谷数据水,然而咱最终还是没有卡过uoj上的毒瘤数据-- 神tm全uoj就3个人过了这题-- 首先,每个数最多被开根\(6\)次,开到\(1\)之后就别管它了,把它用并查集连到它父亲上 它 ...
随机推荐
- [转]scala和RDD中的占位符"_"
1.通配符.类似Java中的*.如:import scala.math._ 2.作为一个整体.:_*,告诉编译器你希望将某个参数当作参数序列处理!例如val s = sum(1 to 5:_*)就是将 ...
- 浏览器关闭后Session真的消失了吗?
今天想和大家分享一个关于Session的话题: 当浏览器关闭时,Session就被销毁了? 我们知道Session是JSP的九大内置对象(也叫隐含对象)中的一个,它的作用是可以保 存当前用户的状态信 ...
- org.springframework.util.Base64Utils线程安全问题
Spring提供的org.springframework.util.Base64Utils类,先会检测JDK里是否自带java.util.Base64,如果不带,则使用的是apache提供的org.a ...
- Abp vNext框架 从空项目开始 使用ASP.NET Core Web Application-笔记
参考 Abp vNext框架 从空项目开始 使用ASP.NET Core Web Application http://www.vnfan.com/helinbin/d/745b1e040c9b4f6 ...
- 最好用的koa2+mysql的RESTful API脚手架,mvc架构,支持node调试,pm2部署。
#基于webpack构建的 Koa2 restful API 服务器脚手架 这是一个基于 Koa2 的轻量级 RESTful API Server 脚手架,支持 ES6, 支持使用TypeSc ...
- 字体图标引入到HTML---复制用代码
第一步:在样式里面声明字体: 告诉别人我们自己定义的字体 ps: font-family的名字可以自己起 src是引入了4种字体,不用修改的 @font-face { font-family: 'ic ...
- overflow-x:scroll失效问题解决
在移动设备上设置overflow-x:scroll,大部分机型都是展示正常的,在安卓哦5.0系统上,无论怎么样滚动条都不会生效,终于找到了解决办法: display: -webkit-box; // ...
- Kali linux-信息收集-dmitry
信息收集-dmitry DMitry(Deepmagic Information Gathering Tools 深度信息收集工具)是一个kali linux下用C语言写的工具.主要功能为端口扫描,w ...
- php 的定界符 <<<eof
PHP是一个Web编程语言,在编程过程中难免会遇到用echo来输出大段的html和javascript脚本的情况,如果用传统的输出方法 ——按字符串输出的话,肯定要有大量的转义符来对字符串中的引号等特 ...
- 登录界面storyboard的一种布局方法
布局思想:三个大点的背景视图宽高相等间距一定(30),左右距父视图距离一定(50),则宽度确定,水平方向位置确定 竖直方向:高度与宽度成一定比例,上边距父视图距离一定,竖直方向的位置和大小也确定了.输 ...