3237: [Ahoi2013]连通图 线段树分治
题解:
cf765f
cf671e
bzoj4184
bzoj4552
线段树分治裸题
还是介绍一下线段树分治
这个东西其实挺简单但也挺有用的
可以把删除+插入操作变成只有插入(倒着就是删除)
像这一道题,我们对时间点建立线段树
对一段区间共同有的元素依次加入到线段树中(开个队列维护一下)
发现这样是只有nlogn个点
另外这个标记显然是可以标记永久化的
apio t1是这个所以就学习了一下
为了练习一下可持久化并查集于是我就写了
然后主席树造成了它一定会mle。。nlognlog(nlogn)
其实只用带撤销的并查集就可以了
#include <bits/stdc++.h>
using namespace std;
const int N=4e7+;
const int N2=3e5+;
struct re{
int x,y;
}a[N2];
int cnt,now,n,m,k;
int ls[N],rs[N],data[N];
int ph[N2*],pt[N2*],count2[N2],f[N2];
bool ft[N2];
vector<int> ve[N2*];
#define mid (ph[x]+pt[x])/2
void change(int last,int &now,int h,int t,int goal,int goal2)
{
now=++cnt;
if (h==t)
{
data[now]=goal2;
return;
}
ls[now]=ls[last];
rs[now]=rs[last];
int mid2=(h+t)/;
if (goal<=mid2) change(ls[last],ls[now],h,mid2,goal,goal2);
else change(rs[last],rs[now],mid2+,t,goal,goal2);
}
int query(int x,int h,int t,int goal)
{
if (h==t) return(data[x]);
int mid2=(h+t)/;
if (goal<=mid2) return(query(ls[x],h,mid2,goal));
else return(query(rs[x],mid2+,t,goal));
}
void build(int x,int h,int t)
{
ph[x]=h; pt[x]=t;
if (h==t) return;
build(x*,h,mid); build(x*+,mid+,t);
}
void insert(int x,int h,int t,int goal)
{
if (h<=ph[x]&&pt[x]<=t)
{
ve[x].push_back(goal);
return;
}
if (h<=mid) insert(x*,h,t,goal);
if (mid<t) insert(x*+,h,t,goal);
}
int find(int root,int x)
{
int y=query(root,,N,x);
if (y==x) return(x);
else return(find(root,y));
}
void dfs(int x,int h,int t,int ans)
{
stack<re> s;
int now1=now;
int len=ve[x].size();
for (int i=;i<len;i++)
{
int x1=a[ve[x][i]].x,x2=a[ve[x][i]].y;
int x11=find(now,x1),x22=find(now,x2);
if (x11!=x22)
{
if (count2[x11]>count2[x22]) swap(x11,x22);
change(now,now,,N,x11,x22);
s.push(re{x22,count2[x22]});
count2[x22]+=count2[x11];
ans++;
}
}
if (h==t)
{
if (ans==n-) ft[h]=; else ft[h]=;
} else
{
dfs(x*,h,(h+t)/,ans);
dfs(x*+,(h+t)/+,t,ans);
}
while (!s.empty())
{
re x=s.top(); s.pop();
count2[x.x]=x.y;
}
now=now1;
}
int main()
{
freopen("3237.in","r",stdin);
freopen("3237.out","w",stdout);
cin>>n>>m;
for (int i=;i<=m;i++)
{
cin>>a[i].x>>a[i].y;
}
cin>>k;
for (int i=;i<=n;i++) f[i]=;
for (int i=;i<=n;i++)
{
change(now,now,,N,i,i);
count2[i]=;
}
build(,,k);
for (int i=;i<=k;i++)
{
int nown,x;
cin>>nown;
for (int j=;j<=nown;j++)
{
cin>>x;
if (i->=f[x])
{
insert(,f[x],i-,x);
}
f[x]=i+;
}
}
for (int i=;i<=m;i++)
if (f[i]<=k)
insert(,f[i],k,i);
dfs(,,k,);
for (int i=;i<=k;i++)
if (ft[i]==) cout<<"Connected"<<endl;
else cout<<"Disconnected"<<endl;
return ;
}
这个是正确的
#include <bits/stdc++.h> using namespace std; const int N=4e7+; const int N2=3e5+;
#define rint register int
struct re{ int x,y,z; }a[N2];
char ss[<<],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;}
template<class T>void read(T&x){
rint f=,c;while(c=gc(),c<||<c)if(c=='-')f=-;x=c^;
while(c=gc(),<c&&c<)x=(x<<)+(x<<)+(c^);x*=f;
}
int cnt,now,n,m,k; int ph[N2*],pt[N2*],fa[N2],count2[N2],f[N2]; bool ft[N2]; vector<int> ve[N2*]; #define mid (ph[x]+pt[x])/2 void build(int x,int h,int t) { ph[x]=h; pt[x]=t; if (h==t) return; build(x*,h,mid); build(x*+,mid+,t); } void insert(int x,int h,int t,int goal) { if (h<=ph[x]&&pt[x]<=t) { ve[x].push_back(goal); return; } if (h<=mid) insert(x*,h,t,goal); if (mid<t) insert(x*+,h,t,goal); } int find(int x) { int y=fa[x]; if (y==x) return(x); else return(find(y)); } void dfs(int x,int h,int t,int ans) { stack<re> s; int now1=now; int len=ve[x].size(); for (int i=;i<len;i++) { int x1=a[ve[x][i]].x,x2=a[ve[x][i]].y; int x11=find(x1),x22=find(x2); if (x11!=x22) { if (count2[x11]>count2[x22]) swap(x11,x22); fa[x11]=x22; s.push(re{x22,count2[x22],x11}); count2[x22]+=count2[x11]; ans++; } } if (h==t) { if (ans==n-) ft[h]=; else ft[h]=; } else { dfs(x*,h,(h+t)/,ans); dfs(x*+,(h+t)/+,t,ans); } while (!s.empty()) { re x=s.top(); s.pop(); count2[x.x]=x.y;
fa[x.z]=x.z; } now=now1; } int main() { freopen("3237.in","r",stdin); freopen("3237.out","w",stdout); read(n); read(m); for (int i=;i<=m;i++) { read(a[i].x); read(a[i].y);
} read(k); for (int i=;i<=n;i++) f[i]=; for (int i=;i<=n;i++) { fa[i]=i; count2[i]=; } build(,,k); for (int i=;i<=k;i++) { int nown,x; read(nown); for (int j=;j<=nown;j++) { read(x); if (i->=f[x]) { insert(,f[x],i-,x); } f[x]=i+; } } for (int i=;i<=m;i++) if (f[i]<=k) insert(,f[i],k,i); dfs(,,k,); for (int i=;i<=k;i++) if (ft[i]==) puts("Connected"); else puts("Disconnected"); return ; }
3237: [Ahoi2013]连通图 线段树分治的更多相关文章
- BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)
Description Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connec ...
- 线段树分治初步学习&洛谷P5227[AHOI2013]连通图
线段树分治 其实思想说起来是比较简单的,我们把这个题里的所有操作(比如连边删边查询balabala)全部拍到一棵线段树上,然后对着整棵树dfs一下求解答案,顺便把操作做一下,回溯的时候撤销一下即可.虽 ...
- 【线段树分治】【P5227】 [AHOI2013]连通图
Description 给定一个无向连通图和若干个小集合,每个小集合包含一些边,对于每个集合,你需要确定将集合中的边删掉后改图是否保持联通.集合间的询问相互独立 定义一个图为联通的当且仅当对于任意的两 ...
- BZOJ3237 AHOI2013连通图(线段树分治+并查集)
把查询看做是在一条时间轴上.那么每条边都有几段存在时间.于是线段树分治就好了. 然而在bzoj上t掉了,不知道是常数大了还是写挂了. 以及brk不知道是啥做数组名过不了编译. #include< ...
- 线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)
闲话 stO猫锟学长,满脑子神仙DS 网上有不少Dalao把线段树分治也归入CDQ分治? 还是听听YCB巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义 ...
- BZOJ 3237: [Ahoi2013]连通图
3237: [Ahoi2013]连通图 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1161 Solved: 399[Submit][Status ...
- 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横
不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...
- LOJ2312 LUOGU-P3733「HAOI2017」八纵八横 (异或线性基、生成树、线段树分治)
八纵八横 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个 ...
- BZOJ 3237([Ahoi2013]连通图-cdq图重构-连通性缩点)
3237: [Ahoi2013]连通图 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 106 Solved: 31 [ Submit][ St ...
随机推荐
- html接收参数
代码 <!DOCTYPE html> <html> <head> <title>html接收参数</title> </head> ...
- 基于Selenium的Web自动化框架增强篇
在写完上一篇“基于Selenium的Web自动化框架”(http://www.cnblogs.com/AlwinXu/p/5836709.html)之后一直没有时间重新审视该框架,正好趁着给同事分享的 ...
- MySQL事物(一)事务隔离级别和事物并发冲突
数据库的操作通常为写和读,就是所说的CRUD:增加(Create).读取(Read).更新(Update)和删除(Delete).事务就是一件完整要做的事情.事务是恢复和并发控制的基本单位.事务必须始 ...
- Oracle——环比增长率
首先,了解什么是:环比增长率? 环比增长率=(本期数-上期数)÷上期数×100% 如:2014年2月的工资为:5000,2014年1月的工资为4000,则2月份的环比增长率为: (5000-4000) ...
- matplotlib-2D绘图库
安装 python -m pip install matplotlib 允许中文: 使用matplotlib的字体管理器指定字体文件 plt.rcParams['font.sans-serif'] ...
- [C++]数组与指针(纯代码-复习用)
#include<iostream> #include<cmath> //C++ //#include<math.h> //C #include<ctime& ...
- python中的%s%是什么意思
它是一个字符串格式化语法(它从C借用). 请参阅 “格式化字符串”: Python支持将值格式化为字符串.虽然这可以包括非常复杂的表达式,但最基本的用法是将值插入到%s 占位符的字符串中 . 编辑 ...
- SpringBoot2.x过滤器Filter和使用Servlet3.0配置自定义Filter实战
补充:SpringBoot启动日志 1.深入SpringBoot2.x过滤器Filter和使用Servlet3.0配置自定义Filter实战(核心知识) 简介:讲解SpringBoot里面Filter ...
- kdevelop 添加对 C++11的支持
工程--打开配置--显示高级--显示高级变量(打钩) CMAKE_CXX_FLAGS 项添加 -std=c++0x
- eMMC基础技术8:操作模式1-boot mode
1.前言 eMMC总线操作包含: boot mode device identification mode interrupt mode data transfer mode 本文主要描述boot m ...