BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述

输入
输出
包含若干行,每行一个整数。即对于输入中的每个询问,依次输出一个答案。
样例输入
1 2
2 3
2 4
1 5
.#
..
#.
.#
..
Q 5 3
C 1 ##
Q 4 5
样例输出
3
题目大意:给一棵树,树上每个点分为AB两个区域,每个区域可能是空地或障碍物,每次可以从一个点的一个区域走到相邻点的相同区域或走到这个点的另一个区域,每次能走的前提是走到的区域是空地,一个点的一个区域只能走一次(也就是说从一个区域走出去就不能走回来了)。有两种操作:1、修改一个点的两个区域。2、查询从u的任意空地区域走到v最多能走多少步,可以不到达v,如果u无空地输出0。
显然是用树链剖分+线段树,线段树维护连通性(最长路)。
维护连通性的方法和BZOJ1018类似(建议先做一下bzoj1018再做这道题)。
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
struct miku
{
int luru;
int ldrd;
int lurd;
int ldru;
int lumx;
int ldmx;
int rumx;
int rdmx;
int l,r;
}t[400010];
int n,m;
int x,y;
int num;
int tot;
char c[4];
char ch[4];
int f[50010];
int d[50010];
int s[50010];
int q[50010];
int to[100010];
int son[50010];
int top[50010];
int size[50010];
int head[50010];
int a[50010][4];
int next[100010];
void add(int x,int y)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void dfs(int x)
{
size[x]=1;
d[x]=d[f[x]]+1;
for(int i=head[x];i;i=next[i])
{
if(to[i]!=f[x])
{
f[to[i]]=x;
dfs(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]])
{
son[x]=to[i];
}
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
s[x]=++num;
q[num]=x;
if(son[x])
{
dfs2(son[x],tp);
}
for(int i=head[x];i;i=next[i])
{
if(to[i]!=f[x]&&to[i]!=son[x])
{
dfs2(to[i],to[i]);
}
}
}
void merge(miku &z,miku x,miku y)
{
z.l=x.l;
z.r=y.r;
z.luru=0;
if(a[q[x.r]][1]&&a[q[y.l]][1]&&x.luru&&y.luru)
{
z.luru=max(x.luru+y.luru,z.luru);
}
if(a[q[x.r]][2]&&a[q[y.l]][2]&&x.lurd&&y.ldru)
{
z.luru=max(x.lurd+y.ldru,z.luru);
}
z.lurd=0;
if(a[q[x.r]][1]&&a[q[y.l]][1]&&x.luru&&y.lurd)
{
z.lurd=max(x.luru+y.lurd,z.lurd);
}
if(a[q[x.r]][2]&&a[q[y.l]][2]&&x.lurd&&y.ldrd)
{
z.lurd=max(x.lurd+y.ldrd,z.lurd);
}
z.ldru=0;
if(a[q[x.r]][1]&&a[q[y.l]][1]&&x.ldru&&y.luru)
{
z.ldru=max(x.ldru+y.luru,z.ldru);
}
if(a[q[x.r]][2]&&a[q[y.l]][2]&&x.ldrd&&y.ldru)
{
z.ldru=max(x.ldrd+y.ldru,z.ldru);
}
z.ldrd=0;
if(a[q[x.r]][1]&&a[q[y.l]][1]&&x.ldru&&y.lurd)
{
z.ldrd=max(x.ldru+y.lurd,z.ldrd);
}
if(a[q[x.r]][2]&&a[q[y.l]][2]&&x.ldrd&&y.ldrd)
{
z.ldrd=max(x.ldrd+y.ldrd,z.ldrd);
}
z.lumx=x.lumx;
if(a[q[x.r]][1]&&a[q[y.l]][1]&&x.luru)
{
z.lumx=max(x.luru+y.lumx,z.lumx);
}
if(a[q[x.r]][2]&&a[q[y.l]][2]&&x.lurd)
{
z.lumx=max(x.lurd+y.ldmx,z.lumx);
}
z.ldmx=x.ldmx;
if(a[q[x.r]][1]&&a[q[y.l]][1]&&x.ldru)
{
z.ldmx=max(x.ldru+y.lumx,z.ldmx);
}
if(a[q[x.r]][2]&&a[q[y.l]][2]&&x.ldrd)
{
z.ldmx=max(x.ldrd+y.ldmx,z.ldmx);
}
z.rumx=y.rumx;
if(a[q[x.r]][1]&&a[q[y.l]][1]&&y.luru)
{
z.rumx=max(y.luru+x.rumx,z.rumx);
}
if(a[q[x.r]][2]&&a[q[y.l]][2]&&y.ldru)
{
z.rumx=max(y.ldru+x.rdmx,z.rumx);
}
z.rdmx=y.rdmx;
if(a[q[x.r]][1]&&a[q[y.l]][1]&&y.lurd)
{
z.rdmx=max(y.lurd+x.rumx,z.rdmx);
}
if(a[q[x.r]][2]&&a[q[y.l]][2]&&y.ldrd)
{
z.rdmx=max(y.ldrd+x.rdmx,z.rdmx);
}
}
void build(int rt,int l,int r)
{
if(l==r)
{
t[rt].l=l;
t[rt].r=r;
if(a[q[l]][1]==1&&a[q[l]][2]==1)
{
t[rt].luru=t[rt].ldrd=1;
t[rt].lurd=t[rt].ldru=2;
t[rt].lumx=t[rt].ldmx=t[rt].rumx=t[rt].rdmx=2;
}
else if(a[q[l]][1]==1&&a[q[l]][2]==0)
{
t[rt].luru=t[rt].lumx=t[rt].rumx=1;
}
else if(a[q[l]][1]==0&&a[q[l]][2]==1)
{
t[rt].ldrd=t[rt].ldmx=t[rt].rdmx=1;
}
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
merge(t[rt],t[rt<<1],t[rt<<1|1]);
}
void clear(miku &x)
{
x.luru=x.lurd=x.ldru=x.ldrd=0;
x.lumx=x.ldmx=x.rumx=x.rdmx=0;
}
void change(int rt,int l,int r,int k)
{
if(l==r)
{
clear(t[rt]);
if(a[q[l]][1]==1&&a[q[l]][2]==1)
{
t[rt].luru=t[rt].ldrd=1;
t[rt].lurd=t[rt].ldru=2;
t[rt].lumx=t[rt].ldmx=t[rt].rumx=t[rt].rdmx=2;
}
else if(a[q[l]][1]==1&&a[q[l]][2]==0)
{
t[rt].luru=t[rt].lumx=t[rt].rumx=1;
}
else if(a[q[l]][1]==0&&a[q[l]][2]==1)
{
t[rt].ldrd=t[rt].ldmx=t[rt].rdmx=1;
}
return ;
}
int mid=(l+r)>>1;
if(k<=mid)
{
change(rt<<1,l,mid,k);
}
else
{
change(rt<<1|1,mid+1,r,k);
}
merge(t[rt],t[rt<<1],t[rt<<1|1]);
}
miku query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return t[rt];
}
int mid=(l+r)>>1;
if(R<=mid)
{
return query(rt<<1,l,mid,L,R);
}
if(L>mid)
{
return query(rt<<1|1,mid+1,r,L,R);
}
miku res;
merge(res,query(rt<<1,l,mid,L,R),query(rt<<1|1,mid+1,r,L,R));
return res;
}
void rotate(miku &x)
{
swap(x.lurd,x.ldru);
swap(x.lumx,x.rumx);
swap(x.ldmx,x.rdmx);
swap(x.l,x.r);
}
int lca(int x,int y)
{
miku res;
miku ans;
clear(ans);
clear(res);
int tx=0;
int ty=0;
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]])
{
if(tx==0)
{
res=query(1,1,n,s[top[x]],s[x]);
tx=1;
}
else
{
merge(res,query(1,1,n,s[top[x]],s[x]),res);
}
x=f[top[x]];
}
else
{
if(ty==0)
{
ans=query(1,1,n,s[top[y]],s[y]);
ty=1;
}
else
{
merge(ans,query(1,1,n,s[top[y]],s[y]),ans);
}
y=f[top[y]];
}
}
if(d[x]<d[y])
{
rotate(res);
if(tx==0)
{
res=query(1,1,n,s[x],s[y]);
}
else
{
merge(res,res,query(1,1,n,s[x],s[y]));
}
if(ty!=0)
{
merge(res,res,ans);
}
return max(res.lumx,res.ldmx);
}
else
{
if(ty!=0)
{
rotate(ans);
}
if(tx==0)
{
res=query(1,1,n,s[y],s[x]);
}
else
{
merge(res,query(1,1,n,s[y],s[x]),res);
}
if(ty!=0)
{
merge(res,ans,res);
}
return max(res.rumx,res.rdmx);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
{
scanf("%s",ch);
if(ch[0]=='.')
{
a[i][1]=1;
}
else
{
a[i][1]=0;
}
if(ch[1]=='.')
{
a[i][2]=1;
}
else
{
a[i][2]=0;
}
}
dfs(1);
dfs2(1,1);
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%s",c);
if(c[0]=='Q')
{
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
else
{
scanf("%d",&x);
scanf("%s",ch);
if(ch[0]=='.')
{
a[x][1]=1;
}
else
{
a[x][1]=0;
}
if(ch[1]=='.')
{
a[x][2]=1;
}
else
{
a[x][2]=0;
}
change(1,1,n,s[x]);
}
}
}
BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树的更多相关文章
- 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并
题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- 通过socket获取图片并保存
网络操作的相关API gethostbyname/gethostbyaddr/getservbyname struct hostent *gethostbyname(const char *name) ...
- 如何在Skyline中加载ArcGISServer发布的WMS和WMTS服务
如何在Skyline中加载ArcGISServer发布的WMS和WMTS服务? 我这里的测试环境是ArcGISServer10.1和TerraExplorer Pro7.0,主要过程截图如下,
- java JDK安装教程
JAVA_HOME G:\JDK\java7\jdk1.7.0_80 根据自己的哈 ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin 然后找到CLASSPATH ...
- docker for windows 10 添加阿里云镜像仓库无效问题
原来一直是用cmd来执行docker 命令的,结果今天发现不行了,改了镜像仓库也pull不下来. 后来换用powerShell执行docker pull 才成功.大家可以试试 win+R 运行 po ...
- Luogu P2482 [SDOI2010]猪国杀
这道题在模拟界地位不亚于Luogu P4604 [WC2017]挑战在卡常界的地位了吧. 早上到机房开始写,中间因为有模拟赛一直到1点过才正式开始码. 一边膜拜CXR dalao一边写到3点左右,然后 ...
- Luogu P1514 引水入城
我承认我有点懒(洛谷已经发过题解了,但我发誓要坚持写博客) 这道题坑了我3天…… 首先一看就与染色问题类似,果断BFS(写DFS炸了) 先将最上面(靠近水)的一行全部扔进队列里,做一遍BFS 再对最下 ...
- ES6入门之let、cont
一.前提 解决ES5中只有全局作用域和函数作用域,没有块级作用域而带来的不合理的场景. let 基本用法 用法和var 一样,只是let声明的变量只有在let命令所在的代码块有效 { let a = ...
- 基于uFUN开发板的心率计(三)Qt上位机的实现
前言 上两周利用周末的时间,分别写了基于uFUN开发板的心率计(一)DMA方式获取传感器数据和基于uFUN开发板的心率计(二)动态阈值算法获取心率值,介绍了AD采集传感器数据和数据的滤波处理获取心率值 ...
- 软件工程项目之摄影App(第二次冲刺)
第二次冲刺阶段做出了登录,还有首页.基本界面也成型了. 登录验证码是用了mob的验证码skd.
- MCMC等采样算法
一.直接采样 直接采样的思想是,通过对均匀分布采样,实现对任意分布的采样.因为均匀分布采样好猜,我们想要的分布采样不好采,那就采取一定的策略通过简单采取求复杂采样. 假设y服从某项分布p(y),其累积 ...