BZOJ 4285 使者 (CDQ分治+dfs序)
题目大意:给你一棵树,有三种操作,在两个点之间连一个传送门,拆毁一个已有的传送门,询问两个点之间的合法路径数量。一条合法路径满足 1.经过且仅经过一个传送门 2.不经过起点终点简单路径上的任何一条边
这模型转化好神啊
首先把树拍成$dfs$序
问题是在树上,我们把$x,y$这条链拎出来摊平,那么链上每个点都挂了一些子树。
容易发现合法路径数=连接以$x,y$为根的子树的传送门数量
而无根树并没有“子树”这一概念,所以先随便挑一个根跑出来dfs序。
发现“子树”的$dfs$序一定是一个或两个连续的区间,我们分$x,y$是否为$lca$讨论一下就可以了
然后把问题放到二维坐标系上。
问题转化成,动态在一个二维平面内加入/删除一个点,以及查询矩形内点的数量
由于存在修改操作,需要再加上一维。那么整个问题变成了一个三维偏序问题。用$CDQ$分治+树状数组即可
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 100005
#define M1 500005
#define ll long long
#define uint unsigned int
using namespace std; template <typename _T> void read(_T &ret)
{
ret=; _T fh=; char c=getchar();
while(c<''||c>''){ if(c=='-') fh=-; c=getchar(); }
while(c>=''&&c<=''){ ret=ret*+c-''; c=getchar(); }
ret=ret*fh;
} struct Edge{
int to[N1*],nxt[N1*],head[N1],cte;
void ae(int u,int v)
{ cte++; to[cte]=v; nxt[cte]=head[u]; head[u]=cte; }
}e; int n; namespace Tree{
int dep[N1],fa[N1],ff[N1][],st[N1],ed[N1],ord[N1],cur;
void dfs1(int x)
{
int j,v; ff[x][]=x; st[x]=++cur; ord[cur]=x;//sz[x]=1;
for(j=e.head[x];j;j=e.nxt[j])
{
v=e.to[j]; if(v==fa[x]) continue;
fa[v]=x; ff[v][]=x; dep[v]=dep[x]+;
dfs1(v);
}
ed[x]=cur;
}
void init()
{
dep[]=; dfs1();
int i,j;
for(j=;j<=;j++)
for(i=;i<=n;i++)
ff[i][j]=ff[ ff[i][j-] ][j-];
}
int LCA(int x,int y)
{
int i,ans=;
if(dep[x]<dep[y]) swap(x,y);
for(i=;i>=;i--)
if(dep[ff[x][i]]>=dep[y]) x=ff[x][i];
if(x==y) return x;
for(i=;i>=;i--)
if(ff[x][i]==ff[y][i]) ans=ff[x][i];
else x=ff[x][i], y=ff[y][i];
return ans;
}
int LCB(int x,int D)
{
int i;
for(i=;i>=;i--)
if(dep[ff[x][i]]>=D) x=ff[x][i];
return x;
}
}; struct BIT{
int sum[N1];
void upd(int x,int w)
{
if(!x) return; int i;
for(i=x;i<=n;i+=(i&(-i)))
sum[i]+=w;
}
int query(int x)
{
int ans=,i;
for(i=x;i>;i-=(i&(-i)))
ans+=sum[i];
return ans;
}
void clr(int x)
{
int i;
for(i=x;i<=n;i+=(i&(-i)))
sum[i]=;
}
}bit; struct OP{ int x,y,t,type,f; }op[M1],tmp[M1];
int cmp2(OP &s1,OP &s2)
{
if(s1.x!=s2.x) return s1.x<s2.x;
if(s1.y!=s2.y) return s1.y<s2.y;
return s1.type<s2.type;
}
int ans[N1],que[M1],isquery[N1],tl; void CDQ(int L,int R)
{
if(L==R) return;
int M=(L+R)>>,i,j,cnt=;
CDQ(L,M); CDQ(M+,R);
for(i=L,j=M+;i<=M&&j<=R;)
{
if(cmp2(op[i],op[j])){
if(!op[i].type) bit.upd(op[i].y,op[i].f), que[++tl]=op[i].y;
tmp[++cnt]=op[i]; i++;
}else{
if(op[j].type) ans[op[j].t]+=op[j].f*bit.query(op[j].y);
tmp[++cnt]=op[j]; j++;
}
}
while(i<=M){ tmp[++cnt]=op[i]; i++; }
while(j<=R){ tmp[++cnt]=op[j]; if(op[j].type) ans[op[j].t]+=op[j].f*bit.query(op[j].y); j++; }
for(i=L;i<=R;i++) op[i]=tmp[i-L+];
while(tl){ bit.clr(que[tl]); tl--; }
} int m,Q1,Q2;
using Tree::st; using Tree::ed; using Tree::dep; using Tree::LCA; using Tree::LCB; int main()
{
scanf("%d",&n);
int i,j,x,y,z,F,q,fl;
for(i=;i<n;i++) read(x), read(y), e.ae(x,y), e.ae(y,x);
Tree::init();
read(Q1);
for(q=;q<=Q1;q++)
{
read(x); read(y);
op[++m]=(OP){st[x],st[y],,,}; op[++m]=(OP){st[y],st[x],,,};
}
read(Q2);
for(q=;q<=Q2;q++) { read(fl); read(x); read(y);
if(fl==){
op[++m]=(OP){st[x],st[y],q,,}; op[++m]=(OP){st[y],st[x],q,,};
}else if(fl==){
op[++m]=(OP){st[x],st[y],q,,-}; op[++m]=(OP){st[y],st[x],q,,-};
}else if(fl==){
F=LCA(x,y); isquery[q]=;
if(x==F||y==F){
if(x==F) swap(x,y); z=LCB(x,dep[F]+);
op[++m]=(OP){ed[x],st[z]-,q,,}; //op[++m]=(OP){ed[x],0,q,1,-1};
op[++m]=(OP){st[x]-,st[z]-,q,,-}; //op[++m]=(OP){st[x]-1,0,q,1,1};
op[++m]=(OP){ed[x],n,q,,}; op[++m]=(OP){ed[x],ed[z],q,,-};
op[++m]=(OP){st[x]-,n,q,,-}; op[++m]=(OP){st[x]-,ed[z],q,,};
}else{
op[++m]=(OP){ed[x],ed[y],q,,}; op[++m]=(OP){ed[x],st[y]-,q,,-};
op[++m]=(OP){st[x]-,ed[y],q,,-}; op[++m]=(OP){st[x]-,st[y]-,q,,};
}
} } CDQ(,m);
for(i=;i<=Q2;i++) if(isquery[i])
printf("%d\n",ans[i]);
return ;
}
BZOJ 4285 使者 (CDQ分治+dfs序)的更多相关文章
- 【bzoj4182】Shopping 树的点分治+dfs序+背包dp
题目描述 给出一棵 $n$ 个点的树,每个点有物品重量 $w$ .体积 $c$ 和数目 $d$ .要求选出一个连通子图,使得总体积不超过背包容量 $m$ ,且总重量最大.求这个最大总重量. 输入 输入 ...
- [BZOJ 3456]城市规划(cdq分治+FFT)
[BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...
- [BZOJ 2989]数列(CDQ 分治+曼哈顿距离与切比雪夫距离的转化)
[BZOJ 2989]数列(CDQ 分治) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...
- 【BZOJ4285】使者 cdq分治+扫描线+树状数组
[BZOJ4285]使者 Description 公元 8192 年,人类进入星际大航海时代.在不懈的努力之下,人类占领了宇宙中的 n 个行星,并在这些行星之间修建了 n - 1 条星际航道,使得任意 ...
- bzoj 4237 稻草人 - CDQ分治 - 单调栈
题目传送门 传送点I 传送点II 题目大意 平面上有$n$个点.问存在多少个矩形使得只有左下角和右上角有点. 考虑枚举左下角这个点.然后看一下是个什么情况: 嗯对,是个单调栈.但不可能暴力去求每个点右 ...
- bzoj 3262 陌上花开 - CDQ分治 - 树状数组
Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...
- BZOJ 2141: 排队 [CDQ分治]
题意: 交换序列中两个元素,求逆序对 做分块做到这道题...一看不是三维偏序嘛.... 作为不会树套树的蒟蒻就写CDQ分治吧.... 对时间分治...x排序...y树状数组... 交换拆成两个插入两个 ...
- BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]
Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...
- BZOJ - 2809 dispatching 主席树+dfs序
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增强忍者们的 ...
随机推荐
- js 里面的 function 与 Function
function 是 js 的标识符 Function 是 js 里面的一个 构造函数 1.new function 与 new Function 的区别 new 运算符在 js 里面是 创建一个自定 ...
- ASP.NET无法检测IE10浏览器,导致无法登录
今天发现在IE10中打开我开发的网站时,无法登入,页面总会自动重新退出到登录页,后经上网查资料发现这是ASP.NET 2.0.3.5和4.0的Bugs,因这些版本的.NET Framework无法识别 ...
- JavaScript Patterns 2.1 Writing Maintainable Code
Revisiting the code after some time has passed requires: • Time to relearn and understand the proble ...
- ubuntu16.04下配置静态ip
ubuntu下配置静态ip 1.先获取ip基本信息 ifconfig enp3s0 Link encap:以太网 硬件地址 2c:4d:54:65:de:6e inet 地址:192.168.199. ...
- ios集合
Foundation framework中用于收集cocoa对象(NSObject对象)的三种集合分别是: NSArray 用于对象有序集合(数组) NSSet 用于对象无序集合 (集合) NSDic ...
- bzoj2662 [BeiJing wc2012]冻结 ——分层图
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2662 分层图: 我也不知道我写的是不是 bfs (dijkstra?). 代码如下: #in ...
- 【WIP】Rails Client Side Document
创建: 2017/09/15 更新: 2019/04/14 删除其他语言的表述 更新: 2017/10/14 标题加上[WIP] 引入JavaScrpit/CSS manifesto n. 货单 ...
- Java数组去重(利用数组,不借助集合)
今天有个同学问我说老师,Java里边数组怎么去重,在不借助List集合的情况下,最后呢我整理了一下,打算发一篇博文,希望能帮助到有用的人,大佬绕过 public static void arrUniq ...
- CTSC+APIO+THUACM游记
退役之前,写点破事乐呵乐呵.. (同DaD3zZ) CTSC Day0 来到丽都 哈哈哈这可是四星级豪华酒店啊 想想要在这住7天 美滋滋 换了半天的房间 也没有换到一起 最后yzy& ...
- 普通平衡树代码。。。Treap
应一些人之邀...发一篇代码 #include <iostream> #include <cstdio> #include <cstdlib> #include & ...