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 ...
随机推荐
- helm 部署 使用 记录
0.概念:Helm作为一个包管理工具, 它把Kubernetes资源(比如deployments.services或 ingress等) 打包到一个chart中,方便我们将其chart保存到chart ...
- Zephyr的Logging
1 前言 刚接触Zephyr,两眼一抹黑,光是阅读代码对系统没什么概念.还需要通过一些日志了解系统的运行机制,以及各种内核行为. 这就需要借助系统的Logging,大体分为两部分System Logg ...
- 没有内涵段子可以刷了,利用Python爬取段友之家贴吧图片和小视频(含源码)
由于最新的视频整顿风波,内涵段子APP被迫关闭,广大段友无家可归,但是最近发现了一个"段友"的app,版本更新也挺快,正在号召广大段友回家,如下图,有兴趣的可以下载看看(ps:我不 ...
- token令牌
本文摘自 WebApi安全性 使用TOKEN+签名验证 首先问大家一个问题,你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或 ...
- Spring Extensible XML
Spring框架从2.0版本开始,提供了基于Schema风格的Spring XML格式用来定义bean的扩展机制.引入Schema-based XML是为了对Traditional的XML配置形式进行 ...
- windows平台快速搭建Linux(CentOS)
VMware简介 VMware Workstation(简称 “虚拟机”)是一款功能强大的桌面虚拟计算机软件,用户可在Windows平台通过VMware软件同时运行不同的操作系统.这对IT开发人员而言 ...
- PCB之PASTE助焊层和SOLDER阻焊层
1.PASTE为焊接层,用于SMT贴片元件的焊接,对应的图形为钢网(钢网上的小孔): 2.SOLDER为阻焊层,它代表的是绿油的涂抹区域,且为负片输出(负片输出指的是图形以外的区域为有效区域): PA ...
- Linux系统安装IDS(snort工具)
第一步:预装daq所需程序 snort使用数据采集器(daq)监听防火墙数据包队列,所以按照daq.需预装的程序有:flex.bison.libcap. sudo apt-get install fl ...
- InnoDB 文件系统
1. 操作系统文件系统inode 2. InnoDB的存储结构 2.1Innodb inode page 参考 http://mysql.taobao.org/monthly/2016/02/01/ ...
- 配置Nginx反向代理WebSocket,以代理noVNC为例
什么是Nginx Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器. Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮 ...