题解:

树链剖分

和普通的树链剖分不一样,这里的线段树不只是要记录x-y的和

而是要记录x左到y左,x左到y右,x右到y左,x右到y右

然后就可以了

代码:

#include<bits/stdc++.h>
const int N=,M=,inf=1e9;
using namespace std;
int n,m,cnt,place,sz,last[N],x,y,deep[N],u,v,fa[N][],son[N],belong[N],pl[N];
char mp[N][];
struct data{int l1,l2,r1,r2,d1,d2,d3,d4;};
struct edge{int to,next;}e[*N];
struct seg{int l,r;data d;}t[*N];
void insert(int u,int v)
{
e[++cnt].to=v;
e[cnt].next=last[u];
last[u]=cnt;
}
data merge(data a,data b)
{
data tmp;
tmp.d1=max(a.d1+b.d1,a.d2+b.d3);
if (tmp.d1<)tmp.d1=-inf;
tmp.d2=max(a.d1+b.d2,a.d2+b.d4);
if (tmp.d2<)tmp.d2=-inf;
tmp.d3=max(a.d3+b.d1,a.d4+b.d3);
if (tmp.d3<)tmp.d3=-inf;
tmp.d4=max(a.d3+b.d2,a.d4+b.d4);
if (tmp.d4<)tmp.d4=-inf;
tmp.l1=max(a.d1+b.l1,a.d2+b.l2);
tmp.l1=max(tmp.l1,a.l1);
if (tmp.l1<)tmp.l1=-inf;
tmp.l2=max(a.d3+b.l1,a.d4+b.l2);
tmp.l2=max(tmp.l2,a.l2);
if (tmp.l2<)tmp.l2=-inf;
tmp.r1=max(b.d1+a.r1,b.d3+a.r2);
tmp.r1=max(tmp.r1,b.r1);
if (tmp.r1<)tmp.r1=-inf;
tmp.r2=max(b.d2+a.r1,b.d4+a.r2);
tmp.r2=max(tmp.r2,b.r2);
if (tmp.r2<)tmp.r2=-inf;
return tmp;
}
void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;
if (l==r)return;
int mid=(l+r)>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
}
void update(int k,int x,char mp[])
{
int l=t[k].l,r=t[k].r;
if(l==r)
{
t[k].d.d1=t[k].d.d2=t[k].d.d3=t[k].d.d4=-inf;
t[k].d.l1=t[k].d.l2=t[k].d.r1=t[k].d.r2=-inf;
if (mp[]=='.')t[k].d.d1=t[k].d.l1=t[k].d.r1=;
if (mp[]=='.')t[k].d.d4=t[k].d.l2=t[k].d.r2=;
if (mp[]=='.'&&mp[]=='.')
t[k].d.d2=t[k].d.d3=t[k].d.l1=t[k].d.l2=t[k].d.r1=t[k].d.r2=;
return;
}
int mid=(l+r)>>;
if (x<=mid)update(k<<,x,mp);
else update(k<<|,x,mp);
t[k].d=merge(t[k<<].d,t[k<<|].d);
}
data query(int k,int x,int y)
{
int l=t[k].l,r=t[k].r;
if (x==l&&y==r)return t[k].d;
int mid=(l+r)>>;
if (mid>=y)return query(k<<,x,y);
else if (mid<x)return query(k<<|,x,y);
else return merge(query(k<<,x,mid),query(k<<|,mid+,y));
}
void dfs1(int x)
{
son[x]=;
for (int i=;i<=;i++)
if (deep[x]>=(<<i))fa[x][i]=fa[fa[x][i-]][i-];
for (int i=last[x];i;i=e[i].next)
{
if(e[i].to==fa[x][])continue;
fa[e[i].to][]=x;
deep[e[i].to]=deep[x]+;
dfs1(e[i].to);
son[x]+=son[e[i].to];
}
}
void dfs2(int x,int chain)
{
pl[x]=++place;belong[x]=chain;
update(,pl[x],mp[x]);
int k=;
for (int i=last[x];i;i=e[i].next)
{
if (e[i].to==fa[x][])continue;
if (son[e[i].to]>son[k])k=e[i].to;
}
if (k)dfs2(k,chain);
for (int i=last[x];i;i=e[i].next)
{
if (e[i].to==k||e[i].to==fa[x][])continue;
dfs2(e[i].to,e[i].to);
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int t=deep[x]-deep[y];
for (int i=;i<=;i++)
if ((<<i)&t)x=fa[x][i];
for (int i=;i>=;i--)
if (fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
if (x==y)return x;
return fa[x][];
}
data solveque(int x,int f,bool flag)
{
data ans;
ans.l1=ans.l2=ans.r1=ans.r2=;
ans.d1=ans.d4=ans.d2=ans.d3=;
while (belong[x]!=belong[f])
{
ans=merge(query(,pl[belong[x]],pl[x]),ans);
x=fa[belong[x]][];
}
if (flag==&&pl[f]+<=pl[x])ans=merge(query(,pl[f]+,pl[x]),ans);
if (!flag)ans=merge(query(,pl[f],pl[x]),ans);
return ans;
}
void que(int x,int y)
{
if (mp[x][]=='#'&&mp[x][]=='#'){puts("");return;}
int f=lca(x,y);
data a=solveque(x,f,),b=solveque(y,f,);
swap(a.d2,a.d3);
swap(a.l1,a.r1);
swap(a.l2,a.r2);
data ans=merge(a,b);
printf("%d\n",max(ans.l1,ans.l2));
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<n;i++)scanf("%d%d",&u,&v),insert(u,v),insert(v,u);
for (int i=;i<=n;i++)scanf("%s",mp[i]);
build(,,n);
dfs1();dfs2(,);
for (int i=;i<=m;i++)
{
char ch[];
scanf("%s",ch);
if (ch[]=='Q')scanf("%d%d",&x,&y),que(x,y);
else
{
scanf("%d",&x);
scanf("%s",mp[x]);
update(,pl[x],mp[x]);
}
}
return ;
}

bzoj2325的更多相关文章

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

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2325 题意概括 给你一棵N个点的树,树上的每个节点有A,B两块区域,且每种区域有两种状态:可以走的 ...

  2. 【BZOJ2325】[ZJOI2011]道馆之战 线段树+树链剖分

    [BZOJ2325][ZJOI2011]道馆之战 Description 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中的每一个冰块都只能经过 ...

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

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

  4. bzoj2325 [ZJOI2011]道馆之战

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

  5. bzoj千题计划243:bzoj2325: [ZJOI2011]道馆之战

    http://www.lydsy.com/JudgeOnline/problem.php?id=2325 设线段树节点区间为[l,r] 每个节点维护sum[0/1][0/1]  从l的A/B区域到r的 ...

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

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

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

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

  8. bzoj2325 [ZJOI2011]道馆之战 树链剖分+DP+类线段树最大字段和

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2325 题解 可以参考线段树动态维护最大子段和的做法. 对于线段树上每个节点 \(o\),维护 ...

  9. [转载]hzwer的bzoj题单

    counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ120 ...

随机推荐

  1. 持续交付的Mesos与Docker导入篇

    变革这个词在当今的数字化时代司空见惯,IT技术每过一段时间就会有一起革新,从WEB2.0.虚拟化.云计算.大数据.微架构.DevOps再到今天的容器Docker与Mesos. Docker的出现方便了 ...

  2. Spark Shuffle(二)Executor、Driver之间Shuffle结果消息传递、追踪(转载)

    1. 前言 在博客里介绍了ShuffleWrite关于shuffleMapTask如何运行,输出Shuffle结果到Shuffle_shuffleId_mapId_0.data数据文件中,每个exec ...

  3. python16_day35【算法】

    一.BTree class BinTreeNode: def __init__(self, data): self.data = data self.lchild = None self.rchild ...

  4. DNS(bind)添加A、CNAME、MX、PTR记录、智能DNS(ACL)

    1.添加一条A记录(记得更改serial): vim /var/named/chroot/etc/lnh.com.zone 重启一下: rndc reload 查看从服务器: 测试结果: master ...

  5. 4.11 Routing -- Loading/Error Substates

    除了在上节中描述的技术,Ember路由器通过使用error和loading substates为自定义异步跳转提供强大而可重写的约定. 一.loading Substates 1. 在跳转过程中,Em ...

  6. zw版【转发·台湾nvp系列Delphi例程】HALCON MoveRectangle

    zw版[转发·台湾nvp系列Delphi例程]HALCON MoveRectangle procedure TForm1.Button1Click(Sender: TObject);var img : ...

  7. python 封装时间常用操作方法-time,datetime

    封装脚本: #encoding=utf-8import timefrom datetime import timedelta,date def date_time_chinese():    prin ...

  8. jQuery源码分析--Event模块(1)

    jQuery的Event模块提供了强大的功能:事件代理,自定义事件,自定义数据等.今天记录一下它实现的原理. 我们都知道,在js的原生事件中,有事件对象和回调函数这两样东西.但是事件对象是只读的,所以 ...

  9. [置顶] SNMP协议详解<三>

    在上篇文章中,说到了SNMPv3主要在安全性方面进行了增强,采用USM(基于用户的安全模型)和VACM(基于视图的访问控制模型)技术.下面我们就主要讲解SNMPv3的报文格式以及基于USM的认证和加密 ...

  10. 20145104张家明 《Java程序设计》第6周学习总结

    20145104张家明 <Java程序设计>第6周学习总结 教材学习内容总结 第10章与11章总结 标准输入输出 System.in: 标准输入,默认关联到键盘(终端输入) System. ...