以下这个做法应该是叫线段树分治。。。

根据修改操作预处理出每条边存在的时间区间[l,r](以操作序号为时间),然后把所有形式化后的修改挂到线段树节点上。

处理完修改后,dfs一遍线段树,进入某个节点时把那个点上所有的修改操作做一遍连边(用按秩合并并查集),出来时再撤销那些连边;那么到达叶节点时,刚好就是完成了这个节点代表的时间所需要的一切修改操作

复杂度O(nlog^2n),比lct要大

这个东西跟cdq分治一样是时间分治,但是好像不能降维的样子(?反正想了很久没想通),不过能在有些有加入、删除、查询操作的题中,把删除操作规避掉

以下代码把线段树避免掉了(其实是处理过程中把树建出来。。。)

 #include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#define pb push_back
using namespace std;
struct Info
{
int fx,fy,dx,dy;
}ttt[];
int tlen;
struct Q
{
bool type;
int l,r,a,b;
};
bool ans[];
int qnum,n,m;
char tmp[];
map<int,int> ma[];
map<int,int>::iterator it;
int fa[],dep[];
int find(int x)
{
for(;x!=fa[x];x=fa[x]);
return x;
}
void add(const Q &x)
{
int fx=find(x.a),fy=find(x.b);++tlen;
ttt[tlen].fx=fx;ttt[tlen].fy=fy;
ttt[tlen].dx=dep[fx];ttt[tlen].dy=dep[fy];
if(dep[fx]>dep[fy]) fa[fy]=fx;
else
{
fa[fx]=fy;
if(dep[fx]==dep[fy]) dep[fy]++;
}
}
void del(int tm)
{
for(int i=,fx,fy;i<=tm;i++)
{
fx=ttt[tlen].fx;fy=ttt[tlen].fy;
fa[fx]=fx;fa[fy]=fy;
dep[fx]=ttt[tlen].dx;dep[fy]=ttt[tlen].dy;
--tlen;
}
}
void solve(const vector<Q> &q,int l,int r)
//当前线段树上区间为[l,r],要处理的询问为q
{
int i,nn=,sz=q.size();
if(l==r)
{
for(i=;i<sz;i++)
if(q[i].type==)
add(q[i]),++nn;
for(i=;i<sz;i++)
if(q[i].type==)
ans[l]=find(q[i].a)==find(q[i].b);
del(nn);
return;
}
int mid=l+(r-l)/;vector<Q> qq1,qq2;
for(i=;i<sz;i++)
{
if(q[i].type==)
{
if(q[i].l<=l&&r<=q[i].r) add(q[i]),++nn;
else
{
if(q[i].l<=mid) qq1.push_back(q[i]);
if(mid<q[i].r) qq2.push_back(q[i]);
}
}
else
{
if(q[i].l<=mid) qq1.pb(q[i]);
else qq2.pb(q[i]);
}
}
solve(qq1,l,mid);
solve(qq2,mid+,r);
del(nn);
}
vector<Q> q;
bool type[];
int main()
{
int i,a,b;
scanf("%d%d",&n,&m);
for(i=;i<=n;i++) fa[i]=i;
for(i=;i<=m;i++)
{
scanf("%s%d%d",tmp,&a,&b);if(a>b) swap(a,b);
if(tmp[]=='Q') q.pb((Q){,i,,a,b}),type[i]=;
else if(tmp[]=='C') ma[a][b]=i;
else if(tmp[]=='D') q.pb((Q){,ma[a][b],i,a,b}),ma[a].erase(b);
}
for(i=;i<=n;i++)
for(it=ma[i].begin();it!=ma[i].end();it++)
q.pb((Q){,it->second,m,i,it->first});
solve(q,,m);
for(i=;i<=m;i++)
if(type[i]==)
puts(ans[i]?"Yes":"No");
return ;
}

洛谷 P2147 [SDOI2008]洞穴勘测的更多相关文章

  1. 洛谷P2147[SDOI2008]洞穴勘测(lct)

    题目描述 辉辉热衷于洞穴勘测. 某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假 ...

  2. [洛谷P2147][SDOI2008]洞穴勘测

    题目大意:有$n$个洞穴,$m$条指令,指令有三种 $Connect\;u\;v$:在$u,v$之间连一条边 $Destroy\;u\;v$:切断$u,v$之间的边 $Query\;u\;v$:询问$ ...

  3. 洛谷 P2147 [SDOI2008]洞穴勘测 (线段树分治)

    题目链接 题解 早就想写线段树分治的题了. 对于每条边,它存在于一段时间 我们按时间来搞 我们可把一条边看做一条线段 我们可以模拟线段树操作,不断分治下去 把覆盖\(l-r\)这段时间的线段筛选出来, ...

  4. 洛谷 P2147 [SDOI2008]洞穴勘测 LCT

    Code: #include <cstdio> #include <algorithm> #include <string> #include <cstrin ...

  5. 洛谷P2147 [SDOI2008] 洞穴勘探 [LCT]

    题目传送门 洞穴勘探 题目描述 辉辉热衷于洞穴勘测. 某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道 ...

  6. 【洛谷P2147】洞穴勘测

    题目大意:维护 N 个点的无向图,支持动态加边和删边,回答两点的连通性. 题解:线段树分治 + 可撤销并查集 询问可以离线,这是线段树分治的基础. 建立在操作时间轴上的线段树称为线段树分治算法. 本题 ...

  7. P2147 [SDOI2008]洞穴勘测(LCT)

    P2147 [SDOI2008]洞穴勘测 裸的LCT. #include<iostream> #include<cstdio> #include<cstring> ...

  8. P2147 [SDOI2008]洞穴勘测

    P2147 [SDOI2008]洞穴勘测 思路 没办法,我就是喜欢板子都想发的人 都是基础操作,不多说了 代码 #include <bits/stdc++.h> #define ls ch ...

  9. 洛谷P2147 [SDOI2008]Cave 洞穴勘测

    题目描述 辉辉热衷于洞穴勘测. 某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假 ...

随机推荐

  1. homebrew -v 或homebrew -doctor报错请检查 .bash_profile是否有误

    homebrew -doctor报错: /usr/local/Library/Homebrew/global.rb:109:in `split': invalid byte sequence in U ...

  2. appium部分api

    转自:http://www.aichengxu.com/view/41510 使用的语言是java,appium的版本是1.3.4,java-client的版本是java-client-2.1.0,建 ...

  3. dp求顺序hdu1160

    题意是仅仅求一次的顺序.先依照速度从大到小排序,速度想等到按体重增序排列. 然后基本就变成了求已定顺序序列的最长递增序列递增,跟那个求一致最大序列和的基本一致. dp[i]里存储的是到当前i最大的递增 ...

  4. SpringMVC -- 第一个简单的程序

    学习springMVC,我们来记录下第一个HelloWord的程序 首先.我们组织须要的jar包 commons-logging-1.1.3.jar spring-aop-4.1.7.RELEASE. ...

  5. luogu3373 【模板】线段树2

    题目大意: 已知一个数列,你需要进行下面三种操作:1.将某区间每一个数乘上x2.将某区间每一个数加上x3.求出某区间每一个数的和 本线段树的标记是个二元组:add和mul,其代表将一个线段中的每一个点 ...

  6. read appSettings in configuration file by XElement with xmlns

    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/how-to-write-queries- ...

  7. Python return语句用法分析

    return 语句 程序运行到所遇到的第一个return即返回(退出def块),不会再运行第二个return. 要返回两个数值,写成一行即可: def a(x,y): if x==y: return ...

  8. 通过Toad工具查看dmp里面的表

    今天有同事要查看dmp里面的表是否有数据,虽然可以把单表数据通过exp导出查看,但还是稍显有点麻烦,要花时间. 无意中发现toad工具可以直接查看dmp里面的表数据. 第一步:Database--&g ...

  9. MySQL 优化之 EXPLAIN 关键字

    MySQL查询优化之explain的深入解析 0. 准备 首先执行如下的 sql 语句: CREATE TABLE IF NOT EXISTS `article` (`id` int(10) unsi ...

  10. I.MX6 不一定要设置BOOT_MODE进入烧录模式

    /************************************************************************* * I.MX6 不一定要设置BOOT_MODE进入 ...