【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 1153 Solved: 421
[Submit][Status][Discuss]
Description

Input
Output
包含若干行,每行一个整数。即对于输入中的每个询问,依次输出一个答案。
Sample Input
1 2
2 3
2 4
1 5
.#
..
#.
.#
..
Q 5 3
C 1 ##
Q 4 5
Sample Output
3
HINT
Source
Solution
树链剖分+线段树维护(类似)连通性。 和 堵塞的交通 维护方法类似。但是并没有做过。
题目大意:每个节点分为ab连个块,这些节点之间联通呈树形,每个节点的ab可能为障碍或者是空地,从一个节点上的a可以到这个节点的b,或者和这个节点联通的所有a(前提是路径上无障碍)。询问节点x到节点y的方向上最多走多少步,支持单点修改.
这样如果是链上的情况,可以等价为一个2*N的矩阵,上面一行表示所有的a,下面一行表示所有的b,等效到树上,就是多个2*1个矩阵连成的树。
维护方法就是,对于一个区间,维护8个量分别表示:
dis[0][0]表示从区间左端点上到右端点上,dis[0][1]表示从区间左端点下到右端点上,dis[1][0]表示从区间左端点上到右端点下,dis[1][1]表示从区间左端点下到右端点下
Dis[0][0]表示从区间左端点上最多移动数,Dis[0][1]表示从区间左端点下最多移动数,Dis[1][0]表示从区间右端点上最多移动数,Dis[1][1]表示从区间右端点下最多移动数
合并的时候就是讨论一下,画画图就可以得到。
有一个问题,在询问路径x-->y时,有一边到LCA的路径是从下到上的,所以在和另一边路径合并答案时要先反向,然后就可以了。
写的时候要注意细节,这个在Codeing的时候由于思路清晰,写的还是十分美观的,就是断断续续自己 想+写+调 搞了近两个小时...(话说题意真是不清晰)
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int x=; char ch=getchar();
while (ch<'' || ch>'') ch=getchar();
while (ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return x;
}
#define MAXN 30010
#define INF 100000000
int N,M,id[MAXN]; char mp[MAXN][];
namespace SegmentTree
{
struct SgtNode
{
int l,r,dis[][],Dis[][];
SgtNode() { l=,r=; memset(dis,,sizeof(dis)); memset(Dis,,sizeof(Dis)); }
inline bool have() {return !dis[][] && !dis[][] && !dis[][] && !dis[][] && !Dis[][] && !Dis[][] && !Dis[][] && !Dis[][];}
inline void rever() { swap(dis[][],dis[][]),swap(Dis[][],Dis[][]),swap(Dis[][],Dis[][]); }
inline void modify(int a,int b)
{
dis[][]=a? :-INF; Dis[][]=Dis[][]=a;
dis[][]=b? :-INF; Dis[][]=Dis[][]=b;
if (a && b) Dis[][]=Dis[][]=Dis[][]=Dis[][]=dis[][]=dis[][]=;
else dis[][]=dis[][]=-INF;
}//单点修改时的赋值
}tree[MAXN<<];
// dis[0][0]表示从区间左端点上到右端点上,dis[0][1]表示从区间左端点下到右端点上,dis[1][0]表示从区间左端点上到右端点下,dis[1][1]表示从区间左端点下到右端点下
// Dis[0][0]表示从区间左端点上最多移动数,Dis[0][1]表示从区间左端点下最多移动数,Dis[1][0]表示从区间右端点上最多移动数,Dis[1][1]表示从区间右端点下最多移动数
#define ls now<<1
#define rs now<<1|1
inline void update(SgtNode &rt,SgtNode lson,SgtNode rson)
{
SgtNode tmp=rt;
if (lson.have()) {rt=rson; rt.l=tmp.l; rt.r=tmp.r; return;}
if (rson.have()) {rt=lson; rt.l=tmp.l; rt.r=tmp.r; return;}
rt.dis[][]=max( max( lson.dis[][]+rson.dis[][] , lson.dis[][]+rson.dis[][] ) , -INF);
rt.dis[][]=max( max( lson.dis[][]+rson.dis[][] , lson.dis[][]+rson.dis[][] ) , -INF);
rt.dis[][]=max( max( lson.dis[][]+rson.dis[][] , lson.dis[][]+rson.dis[][] ) , -INF);
rt.dis[][]=max( max( lson.dis[][]+rson.dis[][] , lson.dis[][]+rson.dis[][] ) , -INF);
rt.Dis[][]=max( lson.Dis[][] , max( lson.dis[][]+rson.Dis[][] , lson.dis[][]+rson.Dis[][] ) );
rt.Dis[][]=max( lson.Dis[][] , max( lson.dis[][]+rson.Dis[][] , lson.dis[][]+rson.Dis[][] ) );
rt.Dis[][]=max( rson.Dis[][] , max( rson.dis[][]+lson.Dis[][] , rson.dis[][]+lson.Dis[][] ) );
rt.Dis[][]=max( rson.Dis[][] , max( rson.dis[][]+lson.Dis[][] , rson.dis[][]+lson.Dis[][] ) );
}
inline void Update(int now) {update(tree[now],tree[ls],tree[rs]);}
inline void Modify(int now,int pos,char MP[])
{
int l=tree[now].l,r=tree[now].r;
if (l==r) {tree[now].modify(MP[]=='.',MP[]=='.'); return;}
int mid=(l+r)>>;
if (pos<=mid) Modify(ls,pos,MP); else Modify(rs,pos,MP);
Update(now);
}
inline SgtNode Query(int now,int L,int R)
{
int l=tree[now].l,r=tree[now].r;
if (l==L && R==r) return tree[now];
int mid=(l+r)>>; SgtNode ret;
if (R<=mid) return Query(ls,L,R);
else if (L>mid) return Query(rs,L,R);
else return update(ret,Query(ls,L,mid),Query(rs,mid+,R)),ret;
}
inline void Build(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r;
if (l==r) return;
int mid=(l+r)>>;
Build(ls,l,mid); Build(rs,mid+,r);
}
}
using namespace SegmentTree;
namespace Divide
{
struct EdgeNode{int next,to;}edge[MAXN<<];
int head[MAXN],cnt=;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
int deep[MAXN],fa[MAXN],size[MAXN],son[MAXN],pl[MAXN],dfn,top[MAXN];
inline void DFS_1(int now,int last)
{
size[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last)
{
fa[edge[i].to]=now;
deep[edge[i].to]=deep[now]+;
DFS_1(edge[i].to,now);
size[now]+=size[edge[i].to];
if (size[son[now]]<size[edge[i].to]) son[now]=edge[i].to;
}
}
inline void DFS_2(int now,int chain)
{
pl[now]=++dfn; top[now]=chain;
if (son[now]) DFS_2(son[now],chain);
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now] && edge[i].to!=son[now])
DFS_2(edge[i].to,edge[i].to);
}
inline void Modify(int pos,char MP[]) {SegmentTree::Modify(,pl[pos],MP);}
inline void GetAns(int x,int y)
{
SgtNode la,ra,ans; ra.l=ra.r=; la.l=la.r=;
while (top[x]!=top[y])
if (deep[top[x]]<deep[top[y]])
update(ra,Query(,pl[top[y]],pl[y]),ra),y=fa[top[y]];
else
update(la,Query(,pl[top[x]],pl[x]),la),x=fa[top[x]];
if (deep[x]<deep[y])
update(ra,Query(,pl[x],pl[y]),ra);
else
update(la,Query(,pl[y],pl[x]),la);
la.rever(); update(ans,la,ra);
printf("%d\n",max(ans.Dis[][],ans.Dis[][]));
}
inline void BuildTree() {for (int i=; i<=N; i++) Modify(i,mp[i]);}
}
using namespace Divide;
int main()
{
// freopen("fight.in","r",stdin); freopen("fight.out","w",stdout);
N=read(),M=read();
for (int x,y,i=; i<=N-; i++) x=read(),y=read(),InsertEdge(x,y);
Divide::DFS_1(,); Divide::DFS_2(,);
for (int i=; i<=N; i++) scanf("%s",mp[i]+);
SegmentTree::Build(,,N); Divide::BuildTree();
while (M--)
{
char opt[],MP[]; scanf("%s",opt); int L,R,p;
switch (opt[])
{
case 'Q' : L=read(),R=read(); Divide::GetAns(L,R); break;
case 'C' : p=read(); scanf("%s",MP+); Divide::Modify(p,MP); break;
}
}
return ;
}
【BZOJ-2325】道馆之战 树链剖分 + 线段树的更多相关文章
- BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...
- 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并
题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
随机推荐
- android滚动公告栏
项目里要用到开奖公告,单行显示向上滚动的TextView,网上随便找了一个控件发现效果还不错改装一下就可以用到项目里.唯一不妥的地方就是字体大小不太好控制,不是正常的字体大小,也没有深究代码,先把工作 ...
- 学习Maven之Maven Enforcer Plugin
1.Maven Enforcer plugin是什么鬼? 在说这个插件是什么前我们先思考这么一个问题:当我们开发人员进入项目组进行开发前,要准备开发环境,而领导总是会强调工具的统一,编译环境的统一.比 ...
- Redis 支持的5种数据结构
redis的崛起绝非偶然,它确实有自己的新东西在里面,它不像Memcached,只能将数据存储在内存中,它提供了持久化机制和数据同步,避免了宕机后的雪崩的问题,即服务器出现问题后,内存中保留的原始数据 ...
- ORA-00824: cannot set sga_target due to existing internal settings, see alert log for more information
这篇文章是上篇文章”Expdp 导数错误 ORA-00832”的延续,前几天工作比较忙.累,直到今天才整理发出来.这个数据库实例的参数设置比较诡异其实是有原因的,由于这台数据库服务器系统是32位,数据 ...
- Oracle数据库迁移
1 在数据迁移时,用户首先有权限修改数据库,并且进行表空间创建.删除等权利 例如: select * from dba_tab_privs where grantee='SCOT'; ---查看SCO ...
- StarkSoft题库管理系统(二)--生成word格式试卷
一.功能介绍 1.自定义试题库管理系统目录.难易程度,题型,知识库等. 2.试题录入. 3.强大的试题编辑功能,并与通常应用编辑工具有共通. 4.灵活的试卷构造功能,用户可自定 ...
- DB监控-redis监控
公司的redis业务很多,redis监控自然也是DB监控的一大模块,包括采集.展示.监控告警.本文主要介绍redis监控的主要指标和采集方法. 一.Redis监控系统逻辑 1.DBA通过前台页面添加r ...
- iOS AppIcon尺寸和上传ITunes构建版本尺寸
避免忘记. 记录一下 App Icon: 29X2940X4058X5876X7687X8780X80120X120152X152167X167180X180 ITunes构建版本: 1242 x 2 ...
- tomcat的简单安装及配置
实验系统:CentOS 6.6_x86_64 实验前提:防火墙和selinux都关闭 实验软件:apache-tomcat-8.0.24 jdk-8u60-linux-x64 jeecms-v6 一. ...
- nginx 301 永久重定向
nginx301跳转设置很简单,配置如下. (配置文件默认为nginx.conf,如果制定了新的配置文件,在新的文件配置即可.) server{ server_name xxx.com www.xxx ...