http://www.lydsy.com/JudgeOnline/problem.php?id=2325

设线段树节点区间为[l,r]

每个节点维护sum[0/1][0/1]  从l的A/B区域到r的A/B区域 经过冰块的最大数量

mx[0][0] 从l的A区域出发向r经过冰块的最大数量

mx[0][1] 从l的B区域出发向r经过冰块的最大数量

mx[1][0] 从r的A区域出发向l经过冰块的最大数量

mx[1][1] 从r的B区域出发向l经过冰块的最大数量

#include<cstdio>
#include<iostream>
#include<algorithm> #define N 30001 using namespace std; int n; int front[N],nxt[N<<],to[N<<],tot; int fa[N],dep[N],siz[N];
int bl[N]; int id[N],dy[N],cnt; bool a[N][]; #define max(x,y) ((x)>(y) ? (x) : (y)) struct node
{
int sum[][];
int mx[][]; node()
{
for(int i=;i<;++i)
for(int j=;j<;++j)
sum[i][j]=mx[i][j]=;
} node operator + (node p) const
{
node k;
for(int i=;i<=;++i)
for(int j=;j<=;++j)
{
if(sum[i][] && p.sum[][j])
k.sum[i][j]=max(k.sum[i][j],sum[i][]+p.sum[][j]);
if(sum[i][] && p.sum[][j])
k.sum[i][j]=max(k.sum[i][j],sum[i][]+p.sum[][j]);
}
k.mx[][]=max(k.sum[][],k.sum[][]);
k.mx[][]=max(k.sum[][],k.sum[][]);
k.mx[][]=max(k.sum[][],k.sum[][]);
k.mx[][]=max(k.sum[][],k.sum[][]);
if(sum[][]) k.mx[][]=max(k.mx[][],sum[][]+p.mx[][]);
if(sum[][]) k.mx[][]=max(k.mx[][],sum[][]+p.mx[][]);
if(sum[][]) k.mx[][]=max(k.mx[][],sum[][]+p.mx[][]);
if(sum[][]) k.mx[][]=max(k.mx[][],sum[][]+p.mx[][]);
if(p.sum[][]) k.mx[][]=max(k.mx[][],mx[][]+p.sum[][]);
if(p.sum[][]) k.mx[][]=max(k.mx[][],mx[][]+p.sum[][]);
if(p.sum[][]) k.mx[][]=max(k.mx[][],mx[][]+p.sum[][]);
if(p.sum[][]) k.mx[][]=max(k.mx[][],mx[][]+p.sum[][]);
k.mx[][]=max(k.mx[][],mx[][]);
k.mx[][]=max(k.mx[][],mx[][]);
k.mx[][]=max(k.mx[][],p.mx[][]);
k.mx[][]=max(k.mx[][],p.mx[][]);
return k;
} void turn()
{
swap(sum[][],sum[][]);
swap(mx[][],mx[][]);
swap(mx[][],mx[][]);
} }tr[N<<]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
} void dfs1(int x)
{
siz[x]=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x])
{
fa[to[i]]=x;
dep[to[i]]=dep[x]+;
dfs1(to[i]);
siz[x]+=siz[to[i]];
}
} void dfs2(int x,int top)
{
bl[x]=top;
id[x]=++cnt;
dy[cnt]=x;
int y=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x] && siz[to[i]]>siz[y]) y=to[i];
if(y) dfs2(y,top);
else return;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=y && to[i]!=fa[x]) dfs2(to[i],to[i]);
} void build(int k,int l,int r)
{
if(l==r)
{
if(a[dy[l]][]) tr[k].sum[][]=;
if(a[dy[l]][]) tr[k].sum[][]=;
if(a[dy[l]][] && a[dy[l]][]) tr[k].sum[][]=tr[k].sum[][]=;
tr[k].mx[][]=max(tr[k].sum[][],tr[k].sum[][]);
tr[k].mx[][]=max(tr[k].sum[][],tr[k].sum[][]);
tr[k].mx[][]=max(tr[k].sum[][],tr[k].sum[][]);
tr[k].mx[][]=max(tr[k].sum[][],tr[k].sum[][]);
return;
}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
tr[k]=tr[k<<]+tr[k<<|];
} node query(int k,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr) return tr[k];
int mid=l+r>>;
if(opr<=mid) return query(k<<,l,mid,opl,opr);
else if(opl>mid) return query(k<<|,mid+,r,opl,opr);
else return query(k<<,l,mid,opl,opr)+query(k<<|,mid+,r,opl,opr);
} void Query(int u,int v)
{
node ansu,ansv;
bool firstu=false,firstv=false;
while(bl[u]!=bl[v])
{
if(dep[bl[u]]>dep[bl[v]])
{
if(!firstu) firstu=true,ansu=query(,,n,id[bl[u]],id[u]);
else ansu=query(,,n,id[bl[u]],id[u])+ansu;
u=fa[bl[u]];
}
else
{
if(!firstv) firstv=true,ansv=query(,,n,id[bl[v]],id[v]);
else ansv=query(,,n,id[bl[v]],id[v])+ansv;
v=fa[bl[v]];
}
}
if(dep[u]>dep[v])
{
if(!firstu) firstu=true,ansu=query(,,n,id[v],id[u]);
else ansu=query(,,n,id[v],id[u])+ansu;
}
else
{
if(!firstv) firstv=true,ansv=query(,,n,id[u],id[v]);
else ansv=query(,,n,id[u],id[v])+ansv;
}
if(!firstu) ansu=ansv;
else
{
ansu.turn();
if(firstv) ansu=ansu+ansv;
}
cout<<max(ansu.mx[][],ansu.mx[][])<<'\n';
} void change(int k,int l,int r,int x,bool u,bool v)
{
if(l==r)
{
a[l][]=u;
a[l][]=v;
if(a[l][]) tr[k].sum[][]=;
else tr[k].sum[][]=;
if(a[l][]) tr[k].sum[][]=;
else tr[k].sum[][]=;
if(a[l][] && a[l][]) tr[k].sum[][]=tr[k].sum[][]=;
else tr[k].sum[][]=tr[k].sum[][]=;
tr[k].mx[][]=max(tr[k].sum[][],tr[k].sum[][]);
tr[k].mx[][]=max(tr[k].sum[][],tr[k].sum[][]);
tr[k].mx[][]=max(tr[k].sum[][],tr[k].sum[][]);
tr[k].mx[][]=max(tr[k].sum[][],tr[k].sum[][]);
return;
}
int mid=l+r>>;
if(x<=mid) change(k<<,l,mid,x,u,v);
else change(k<<|,mid+,r,x,u,v);
tr[k]=tr[k<<]+tr[k<<|];
} int main()
{
freopen("fight.in","r",stdin);
freopen("fight.out","w",stdout);
int m;
read(n); read(m);
int u,v;
for(int i=;i<n;++i)
{
read(u); read(v);
add(u,v);
}
dfs1();
dfs2(,);
char s[];
for(int i=;i<=n;++i)
{
scanf("%s",s);
if(s[]=='.') a[i][]=true;
if(s[]=='.') a[i][]=true;
}
build(,,n);
char c[];
while(m--)
{
scanf("%s",c);
if(c[]=='Q')
{
read(u); read(v);
Query(u,v);
}
else
{
read(u);
scanf("%s",c);
change(,,n,id[u],c[]=='.',c[]=='.');
}
}
}

bzoj千题计划243:bzoj2325: [ZJOI2011]道馆之战的更多相关文章

  1. bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块

    http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...

  2. bzoj千题计划139:bzoj2229: [Zjoi2011]最小割

    http://www.lydsy.com/JudgeOnline/problem.php?id=2229 最小割树介绍:http://blog.csdn.net/jyxjyx27/article/de ...

  3. bzoj千题计划196:bzoj4826: [Hnoi2017]影魔

    http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...

  4. bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪

    http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...

  5. bzoj千题计划177:bzoj1858: [Scoi2010]序列操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...

  6. bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...

  7. bzoj千题计划304:bzoj3676: [Apio2014]回文串(回文自动机)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3676 回文自动机模板题 4年前的APIO如今竟沦为模板,,,╮(╯▽╰)╭,唉 #include& ...

  8. bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹

    http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...

  9. bzoj千题计划278:bzoj4590: [Shoi2015]自动刷题机

    http://www.lydsy.com/JudgeOnline/problem.php?id=4590 二分 这么道水题 没long long WA了两发,没判-1WA了一发,二分写错WA了一发 最 ...

随机推荐

  1. 【BZOJ4698】Sandy的卡片(后缀数组)

    [BZOJ4698]Sandy的卡片(后缀数组) 题面 讨厌权限题!!! 因为我交不了... 洛谷 题面 做完差之后就是裸的最长公共子串 没了.. 数组往死里开吧... #include<ios ...

  2. [BZOJ1604] [Usaco2008 Open] Cow Neighborhoods 奶牛的邻居 (queue & set)

    Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l ...

  3. SVN提示图标详解

    常见SVN图标的含义  灰色向右箭头:本地修改过 蓝色向左箭头:SVN上修改过 灰色向右且中间有个加号的箭头:本地比SVN上多出的文件 蓝色向左且中间有个加号的箭头:SVN上比本地多出的文件 灰色向右 ...

  4. Gradle下载 Jar 包

    使用此方法下载Jar包的前提是已经配置好了Gradle的环境了,配置好的标志是在终端输入gradle不提示command not found. 1. 编写build.gradle文件代码: apply ...

  5. js实现最长子串算法

    var arr=["weeweadbshow","jhsaasrbgddbshow","ccbshow"]; function Longes ...

  6. 三方面搞定http协议之“状态码”

    当我们向服务器请求数据的时候,服务器会给我们一个反馈,告诉我们对待我们的请求,服务器处理得怎么样了,而这个反馈,是通过数字来传达的,这个数字就叫状态码. 状态码分为以下几种: 1xx:指示信息--表示 ...

  7. char码值对应列表大全

    Char("0") 为0的字符Char("1") Char("2") Char("3") Char("4&qu ...

  8. thinkPHP5使用的一些小配置

    开发环境: 版本:php5.6 系统:windows 工具:phpstudy.vscode 遇到的报错信息error: 一.原php5.4版本(不限定)切换到5.6版本,路由报错: No input ...

  9. 分享基于Qt5开发的一款故障波形模拟软件

    背景介绍 这是一款采用Qt5编写的用于生成故障模拟波形的软件.生成的波形数据用于下发到终端机器生成对应的故障类型,用于培训相关设备维护人员的故障排查技能.因此,在这款软件中实现了故障方案管理.故障波形 ...

  10. workflow--相关笔记

    转自http://blog.csdn.net/u014682573/article/details/29922093 1. 工作流技术 工作流(Workflow) 定义:工作流就是将一组任务组织起来, ...