欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ2325


题意概括

给你一棵N个点的树,树上的每个节点有A,B两块区域,且每种区域有两种状态:可以走的“.”,不能走的“#”。每次只能移动到相邻节点的同一类区域(AA,BB)或这个房间的另一区域(AB,BA)。
现在有Q个操作,操作分两种:
C x s :将x节点A,B的区域的状态改为s
Q x y :询问从x出发走到y(不能往回走)最多可以走过几个区域(可以不走到y)。
N≤ 30 000 , Q ≤ 80 000


题解

对于这道题目,我们很容易就能想到树剖,那么链上的问题就变成序列上的单点修改+区间询问了。
而显然这道题目的信息是可以用线段树来维护的,我们只需要在每个节点上维护8个标记:从左上到右上,从左上到右下,从左下到右上,从左下到右下的最长路径以及从左上,从左下,从右上,从右下出发的最长路径就行了。这些标记都是可以O(1)合并的,所以总的时间复杂度就是 $O(Q\log^2n)$ 了。

 写的时候因为炸int莫名其妙错了很久……


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=30005,Inf=1e7;
int max(int a,int b,int c){return max(a,max(b,c));}
int max(int a,int b,int c,int d){return max(a,max(b,c,d));}
struct Gragh{
int cnt,y[N*2],nxt[N*2],fst[N];
void clear(){
cnt=0;
memset(fst,0,sizeof fst);
}
void add(int a,int b){
y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
}
}g;
int n,m;
int fa[N],size[N],depth[N],son[N],top[N],p[N],ap[N],cnp=0;
int A[N],B[N];
void Get_Gen_Info(int rt,int pre,int d){
fa[rt]=pre,size[rt]=1,depth[rt]=d,son[rt]=-1;
for (int i=g.fst[rt];i;i=g.nxt[i])
if (g.y[i]!=pre){
int s=g.y[i];
Get_Gen_Info(s,rt,d+1);
size[rt]+=size[s];
if (son[rt]==-1||size[s]>size[son[rt]])
son[rt]=s;
}
}
void Get_Top(int rt,int tp){
top[rt]=tp;
ap[p[rt]=++cnp]=rt;
if (son[rt]==-1)
return;
Get_Top(son[rt],tp);
for (int i=g.fst[rt];i;i=g.nxt[i]){
int s=g.y[i];
if (s!=fa[rt]&&s!=son[rt])
Get_Top(s,s);
}
}
struct Tree{
int LA,RA,LB,RB;
int AA,AB,BA,BB;
Tree (){}
Tree (int x){LA=RA=LB=RB=AA=AB=BA=BB=x;}
bool empty(){return !(LA||RA||LB||RB||AA||AB||BA||BB);}
void getnode(int a,int b){//1有路 0障碍
if (a&&b)LA=RA=LB=RB=AB=BA=2,AA=BB=1;
if (a&&!b)LA=RA=AA=1,LB=RB=AB=BA=BB=-Inf;
if (!a&&b)LB=RB=BB=1,LA=RA=AA=AB=BA=-Inf;
if (!a&&!b)LA=RA=LB=RB=AA=AB=BA=BB=-Inf;
}
void rev(){
swap(LA,RA);
swap(LB,RB);
swap(AB,BA);
}
}t[N*4];
Tree operator + (Tree ls,Tree rs){
Tree rt;
if (ls.empty())return rs;
if (rs.empty())return ls;
rt.LA=max(ls.LA,ls.AA+rs.LA,ls.AB+rs.LB,-Inf);
rt.LB=max(ls.LB,ls.BA+rs.LA,ls.BB+rs.LB,-Inf);
rt.RA=max(rs.RA,rs.AA+ls.RA,rs.BA+ls.RB,-Inf);
rt.RB=max(rs.RB,rs.AB+ls.RA,rs.BB+ls.RB,-Inf);
rt.AA=max(ls.AA+rs.AA,ls.AB+rs.BA,-Inf);
rt.AB=max(ls.AA+rs.AB,ls.AB+rs.BB,-Inf);
rt.BA=max(ls.BA+rs.AA,ls.BB+rs.BA,-Inf);
rt.BB=max(ls.BA+rs.AB,ls.BB+rs.BB,-Inf);
return rt;
}
void build(int rt,int L,int R){
if (L==R){
t[rt].getnode(A[ap[L]],B[ap[L]]);
return;
}
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
build(ls,L,mid);
build(rs,mid+1,R);
t[rt]=t[ls]+t[rs];
}
void change(int rt,int L,int R,int pos){
if (L==R){
t[rt].getnode(A[ap[L]],B[ap[L]]);
return;
}
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
if (pos<=mid)
change(ls,L,mid,pos);
else
change(rs,mid+1,R,pos);
t[rt]=t[ls]+t[rs];
}
Tree query(int rt,int L,int R,int xle,int xri){
if (R<xle||L>xri)
return Tree(0);
if (xle<=L&&R<=xri)
return t[rt];
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
return query(ls,L,mid,xle,xri)+query(rs,mid+1,R,xle,xri);
}
int Tquery(int a,int b){
int f1=top[a],f2=top[b],swaped=0,res;
Tree ans,ans1(0),ans2(0);
while (f1!=f2){
if (depth[f1]<depth[f2])
swap(f1,f2),swap(a,b),swap(ans1,ans2),swaped^=1;
ans1=query(1,1,n,p[f1],p[a])+ans1;
a=fa[f1],f1=top[a];
}
if (depth[a]<depth[b])
swap(a,b),swap(ans1,ans2),swaped^=1;
ans1=query(1,1,n,p[b],p[a])+ans1;
if (swaped)
swap(a,b),swap(ans1,ans2);
ans1.rev();
ans=ans1+ans2;
res=max(ans.LA,ans.LB);
return res>0?res:0;
}
int main(){
g.clear();
scanf("%d%d",&n,&m);
for (int i=1,a,b;i<n;++i){
scanf("%d%d",&a,&b);
g.add(a,b);
g.add(b,a);
}
Get_Gen_Info(1,0,0);
Get_Top(1,1);
char s[3];
for (int i=1;i<=n;i++){
scanf("%s",s);
A[i]=s[0]=='.';
B[i]=s[1]=='.';
}
build(1,1,n);
for (int i=1;i<=m;i++){
char op[3];
int x,st,en;
scanf("%s",op);
if (op[0]=='Q'){
scanf("%d%d",&st,&en);
printf("%d\n",Tquery(st,en));
}
else {
scanf("%d%s",&x,s);
A[x]=s[0]=='.';
B[x]=s[1]=='.';
change(1,1,n,p[x]);
}
}
return 0;
}

  

BZOJ2325 [ZJOI2011]道馆之战 树链剖分 线段树的更多相关文章

  1. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  2. 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并

    题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  4. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  5. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  6. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  7. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  8. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  9. 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 ...

  10. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

随机推荐

  1. baiduTemplate.js 百度JS模板引擎

    baiduTemplate希望创造一个用户觉得“简单好用”的JS模板引擎 先展示两个例子,然后说说对baidutemplate.js的理解,从而将这一工具加到个人百宝箱里. <script id ...

  2. MyBatis下MySqL用户口令不能为空

    jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3308/testjdbc.username=testjdbc.pas ...

  3. 解决virtualbox与mac文件拖拽问题

    apt-get purge virtualbox-guest-x11apt-get autoremove --purgerebootapt-get updateapt-get dist-upgrade ...

  4. 法律AI数据及应用

    本文简单列举了法律AI目前的应用,数据集,研究方向. 历史 1970年,Buchanan和Headrick发表文章"关于人工智能和法律推理的一些猜测",讨论了对法律研究和推理进行建 ...

  5. android SQLiteOpenHelper 使用

    1.实体 package mydemo.mycom.demo2.entity; public class UserInfo { private int id; private String usern ...

  6. luogu P2662 牛场围栏

    传送门 因为一个木板可以切掉最多\(m\),所以可以先预处理哪些长度的木板可用,开个桶,然后对\([l-m,l]\)打标记,再把打了标记的数取出来 假设可用长度\(a_1,a_2,,,a_n\)从小到 ...

  7. mysql 案例~mysql主从复制延迟处理(2)

    一 简介:今天来聊聊周期性从库延迟的问题,是上一篇的基础分析的一个场景 二 背景:近期每天的指定时间段,收到从库延迟的报警,然后过一段时间恢复.由于从库是提供读服务的,所以需要解决 三 分析思路: 1 ...

  8. Linux命令行与shell脚本编程大全.第3版(文字版) 超清文字-非扫描版 [免积分、免登录]

    此处免费下载,无需账号,无需登录,无需积分.收集自互联网,侵权通知删除. 点击下载:Linux命令行与shell脚本编程大全.第3版 (大小:约22M)

  9. python - class类 (六) 三大特性 - 多态

    多态的概念: # 多态的概念 # 指出了对象如何通过他们共同的属性和动作来操作及访问而不需考虑他们的具体的类 # 多态表明了动态绑定的存在,允许重载及运行时类型确定和验证. # 示例模拟: #水具有多 ...

  10. npm快捷键

    一.npm基本快捷键 node -v查看安装的nodejs版本,出现版本号,说明刚刚已正确安装nodejs.PS:未能出现版本号,请尝试注销电脑重试: npm -v查看npm的版本号,npm是在安装n ...