题解:

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]连通图 线段树分治的更多相关文章

  1. 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 ...

  2. 线段树分治初步学习&洛谷P5227[AHOI2013]连通图

    线段树分治 其实思想说起来是比较简单的,我们把这个题里的所有操作(比如连边删边查询balabala)全部拍到一棵线段树上,然后对着整棵树dfs一下求解答案,顺便把操作做一下,回溯的时候撤销一下即可.虽 ...

  3. 【线段树分治】【P5227】 [AHOI2013]连通图

    Description 给定一个无向连通图和若干个小集合,每个小集合包含一些边,对于每个集合,你需要确定将集合中的边删掉后改图是否保持联通.集合间的询问相互独立 定义一个图为联通的当且仅当对于任意的两 ...

  4. BZOJ3237 AHOI2013连通图(线段树分治+并查集)

    把查询看做是在一条时间轴上.那么每条边都有几段存在时间.于是线段树分治就好了. 然而在bzoj上t掉了,不知道是常数大了还是写挂了. 以及brk不知道是啥做数组名过不了编译. #include< ...

  5. 线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)

    闲话 stO猫锟学长,满脑子神仙DS 网上有不少Dalao把线段树分治也归入CDQ分治? 还是听听YCB巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义 ...

  6. BZOJ 3237: [Ahoi2013]连通图

    3237: [Ahoi2013]连通图 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1161  Solved: 399[Submit][Status ...

  7. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  8. LOJ2312 LUOGU-P3733「HAOI2017」八纵八横 (异或线性基、生成树、线段树分治)

    八纵八横 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个 ...

  9. BZOJ 3237([Ahoi2013]连通图-cdq图重构-连通性缩点)

    3237: [Ahoi2013]连通图 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 106   Solved: 31 [ Submit][ St ...

随机推荐

  1. html接收参数

    代码 <!DOCTYPE html> <html> <head> <title>html接收参数</title> </head> ...

  2. 基于Selenium的Web自动化框架增强篇

    在写完上一篇“基于Selenium的Web自动化框架”(http://www.cnblogs.com/AlwinXu/p/5836709.html)之后一直没有时间重新审视该框架,正好趁着给同事分享的 ...

  3. MySQL事物(一)事务隔离级别和事物并发冲突

    数据库的操作通常为写和读,就是所说的CRUD:增加(Create).读取(Read).更新(Update)和删除(Delete).事务就是一件完整要做的事情.事务是恢复和并发控制的基本单位.事务必须始 ...

  4. Oracle——环比增长率

    首先,了解什么是:环比增长率? 环比增长率=(本期数-上期数)÷上期数×100% 如:2014年2月的工资为:5000,2014年1月的工资为4000,则2月份的环比增长率为: (5000-4000) ...

  5. matplotlib-2D绘图库

    安装  python -m pip install matplotlib  允许中文: 使用matplotlib的字体管理器指定字体文件 plt.rcParams['font.sans-serif'] ...

  6. [C++]数组与指针(纯代码-复习用)

    #include<iostream> #include<cmath> //C++ //#include<math.h> //C #include<ctime& ...

  7. python中的%s%是什么意思

    它是一个字符串格式化语法(它从C借用). 请参阅  “格式化字符串”: Python支持将值格式化为字符串.虽然这可以包括非常复杂的表达式,但最基本的用法是将值插入到%s 占位符的字符串中  . 编辑 ...

  8. SpringBoot2.x过滤器Filter和使用Servlet3.0配置自定义Filter实战

    补充:SpringBoot启动日志 1.深入SpringBoot2.x过滤器Filter和使用Servlet3.0配置自定义Filter实战(核心知识) 简介:讲解SpringBoot里面Filter ...

  9. kdevelop 添加对 C++11的支持

    工程--打开配置--显示高级--显示高级变量(打钩) CMAKE_CXX_FLAGS   项添加   -std=c++0x

  10. eMMC基础技术8:操作模式1-boot mode

    1.前言 eMMC总线操作包含: boot mode device identification mode interrupt mode data transfer mode 本文主要描述boot m ...