题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2325
题解
假设地图,没有修改操作,那么可以设表示这一段从到,最多可以经过多少个冰块,表示这一段从开始最多能走多远。
转移显然(逃
但是这样显然太慢了,因此我们可以用线段树来优化。
但是带修改怎么办?线段树单点修改,可以证明不会影响到其他的点。
但是原题是在树上,因此可以用树剖来解决。
代码
#include <cstdio>
#include <algorithm>
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int maxn=50000;
const int inf=0x3f3f3f3f;
struct data
{
int len[2][2],far[2][2];
data()
{
len[0][0]=len[0][1]=len[1][0]=len[1][1]=far[0][0]=far[1][0]=far[0][1]=far[1][1]=0;
}
data operator +(const data &other) const
{
if(((*this).len[0][0]==0)&&((*this).len[0][1]==0)&&((*this).len[1][0]==0)&&((*this).len[1][1]==0)&&((*this).far[0][0]==0)&&((*this).far[0][1]==0)&&((*this).far[1][0]==0)&&((*this).far[1][1]==0))
{
return other;
}
if((other.len[0][0]==0)&&(other.len[0][1]==0)&&(other.len[1][0]==0)&&(other.len[1][1]==0)&&(other.far[0][0]==0)&&(other.far[0][1]==0)&&(other.far[1][0]==0)&&(other.far[1][1]==0))
{
return (*this);
}
data ans;
ans.len[0][0]=std::max(len[0][0]+other.len[0][0],len[0][1]+other.len[1][0]);
if(ans.len[0][0]<0)
{
ans.len[0][0]=-inf;
}
ans.len[0][1]=std::max(len[0][0]+other.len[0][1],len[0][1]+other.len[1][1]);
if(ans.len[0][1]<0)
{
ans.len[0][1]=-inf;
}
ans.len[1][0]=std::max(len[1][0]+other.len[0][0],len[1][1]+other.len[1][0]);
if(ans.len[1][0]<0)
{
ans.len[1][0]=-inf;
}
ans.len[1][1]=std::max(len[1][0]+other.len[0][1],len[1][1]+other.len[1][1]);
if(ans.len[1][1]<0)
{
ans.len[1][1]=-inf;
}
ans.far[0][0]=std::max(far[0][0],std::max(len[0][0]+other.far[0][0],len[0][1]+other.far[0][1]));
if(ans.far[0][0]<0)
{
ans.far[0][0]=-inf;
}
ans.far[0][1]=std::max(far[0][1],std::max(len[1][0]+other.far[0][0],len[1][1]+other.far[0][1]));
if(ans.far[0][1]<0)
{
ans.far[0][1]=-inf;
}
ans.far[1][0]=std::max(other.far[1][0],std::max(other.len[0][0]+far[1][0],other.len[1][0]+far[1][1]));
if(ans.far[1][0]<0)
{
ans.far[1][0]=-inf;
}
ans.far[1][1]=std::max(other.far[1][1],std::max(other.len[0][1]+far[1][0],other.len[1][1]+far[1][1]));
if(ans.far[1][1]<0)
{
ans.far[1][1]=-inf;
}
return ans;
}
};
char mp[maxn+10][2],s[10];
namespace sgt
{
data val[maxn<<2];
int updata(int x)
{
val[x]=val[x<<1]+val[x<<1|1];
return 0;
}
int modify(int x,int l,int r,int pos)
{
if(l==r)
{
val[x].len[0][0]=val[x].far[0][0]=val[x].far[1][0]=(mp[pos][0]=='.')?1:-inf;
val[x].len[1][1]=val[x].far[0][1]=val[x].far[1][1]=(mp[pos][1]=='.')?1:-inf;
val[x].len[0][1]=val[x].len[1][0]=((mp[pos][0]=='.')&&(mp[pos][1]=='.'))?2:-inf;
if((mp[pos][0]=='.')&&(mp[pos][1]=='.'))
{
val[x].far[0][0]=val[x].far[1][0]=val[x].far[0][1]=val[x].far[1][1]=2;
}
return 0;
}
int mid=(l+r)>>1;
if(pos<=mid)
{
modify(x<<1,l,mid,pos);
}
else
{
modify(x<<1|1,mid+1,r,pos);
}
updata(x);
return 0;
}
data getval(int x,int l,int r,int askl,int askr)
{
if((askl<=l)&&(r<=askr))
{
return val[x];
}
int mid=(l+r)>>1;
data ans;
if(askl<=mid)
{
ans=ans+getval(x<<1,l,mid,askl,askr);
}
if(mid<askr)
{
ans=ans+getval(x<<1|1,mid+1,r,askl,askr);
}
return ans;
}
}
int n,m,pre[maxn*2+10],now[maxn+10],son[maxn*2+10],tot,deep[maxn+10],dfn[maxn+10],top[maxn+10],wson[maxn+10],fa[maxn+10],size[maxn+10],cnt;
int ins(int a,int b)
{
pre[++tot]=now[a];
now[a]=tot;
son[tot]=b;
return 0;
}
int dfsfirst(int u,int father)
{
fa[u]=father;
deep[u]=deep[father]+1;
size[u]=1;
for(int i=now[u]; i; i=pre[i])
{
int v=son[i];
if(v!=father)
{
dfsfirst(v,u);
size[u]+=size[v];
if((wson[u]==0)||(size[wson[u]]<size[v]))
{
wson[u]=v;
}
}
}
return 0;
}
int dfssecond(int u,int topfather)
{
dfn[u]=++cnt;
top[u]=topfather;
if(wson[u]==0)
{
return 0;
}
dfssecond(wson[u],topfather);
for(int i=now[u]; i; i=pre[i])
{
int v=son[i];
if((v!=fa[u])&&(v!=wson[u]))
{
dfssecond(v,v);
}
}
return 0;
}
int getlca(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
{
std::swap(x,y);
}
x=fa[top[x]];
}
if(deep[x]>deep[y])
{
std::swap(x,y);
}
return x;
}
data getval(int x,int f,int flag)
{
data ans;
while(top[x]!=top[f])
{
ans=sgt::getval(1,1,n,dfn[top[x]],dfn[x])+ans;
x=fa[top[x]];
}
if(flag)
{
ans=sgt::getval(1,1,n,dfn[f],dfn[x])+ans;
}
else
{
if(dfn[f]+1<=dfn[x])
{
ans=sgt::getval(1,1,n,dfn[f]+1,dfn[x])+ans;
}
}
return ans;
}
int solve(int x,int y)
{
int lca=getlca(x,y);
data l=getval(x,lca,1),r=getval(y,lca,0);
std::swap(l.len[0][1],l.len[1][0]);
std::swap(l.far[0][0],l.far[1][0]);
std::swap(l.far[0][1],l.far[1][1]);
data ans=l+r;
return std::max(ans.far[0][0],ans.far[0][1]);
}
int main()
{
n=read();
m=read();
for(int i=1; i<n; ++i)
{
int a=read(),b=read();
ins(a,b);
ins(b,a);
}
dfsfirst(1,0);
dfssecond(1,1);
for(int i=1; i<=n; ++i)
{
scanf("%s",mp[dfn[i]]);
sgt::modify(1,1,n,dfn[i]);
}
while(m--)
{
scanf("%s",s+1);
if(s[1]=='Q')
{
int a=read(),b=read();
int ans=solve(a,b);
if(ans<0)
{
ans=0;
}
printf("%d\n",ans);
}
else
{
int pos=read();
scanf("%s",mp[dfn[pos]]);
sgt::modify(1,1,n,dfn[pos]);
}
}
return 0;
}