当前位置: 首页 > news >正文

P4679 [ZJOI2011] 道馆之战 - Link

题意

给一棵树,每个点有一个两字符的字符串作为权值,其中每个字符为 .#。单点修改,查询从 \(u\) 走到 \(v\),不能经过 #,每个 . 只能经过一次,最多能经过多少个 .

思路

用树剖将树问题转化为序列问题,用线段树维护。每个点存储 \(a_{0/1,0/1}\) 表示当前区间第一步走 \(A/B\) 房间,最后一步走 \(A/B\) 房间的最大点数。\(in_{0/1}\) 表示当前区间从前向后走第一步走 \(A/B\) 房间的最大步数,\(out_{0/1}\) 表示到这走第一步走 \(A/B\) 房间的最大步数。查询链的时候把 \(u\rightarrow v\) 拆分成 \(u\rightarrow lca(u,v)\)\(lca(u,v)\rightarrow v\),要注意一下每条路径的方向。

代码

// Problem: P4679 [ZJOI2011] 道馆之战
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4679
// Memory Limit: 250 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<bits/stdc++.h>
using namespace std;
namespace IO{template<typename T>inline void read(T&x){x=0;char c=getchar();bool f=0;while(!isdigit(c)) c=='-'?f=1:0,c=getchar();while(isdigit(c)) x=x*10+c-'0',c=getchar();f?x=-x:0;}template<typename T>inline void write(T x){if(x==0){putchar('0');return ;}x<0?x=-x,putchar('-'):0;short st[50],top=0;while(x) st[++top]=x%10,x/=10;while(top) putchar(st[top--]+'0');}inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}inline void write(char c){putchar(c);}inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
const int maxn=50010,inf=100000000;
int n,m;
vector<int>e[maxn];
struct node{int a[2][2],in[2],out[2];node(){a[0][0]=a[0][1]=a[1][0]=a[1][1]=in[0]=in[1]=out[0]=out[1]=0;}
};
node merge(node a,node b){node ans;ans.a[0][0]=max(a.a[0][0]+b.a[0][0],a.a[0][1]+b.a[1][0]);ans.a[0][1]=max(a.a[0][0]+b.a[0][1],a.a[0][1]+b.a[1][1]);ans.a[1][0]=max(a.a[1][0]+b.a[0][0],a.a[1][1]+b.a[1][0]);ans.a[1][1]=max(a.a[1][0]+b.a[0][1],a.a[1][1]+b.a[1][1]);ans.in[0]=max({a.in[0],a.a[0][0]+b.in[0],a.a[0][1]+b.in[1],-inf});ans.in[1]=max({a.in[1],a.a[1][0]+b.in[0],a.a[1][1]+b.in[1],-inf});ans.out[0]=max({b.out[0],a.out[0]+b.a[0][0],a.out[1]+b.a[1][0],-inf});ans.out[1]=max({b.out[1],a.out[0]+b.a[0][1],a.out[1]+b.a[1][1],-inf});ans.a[0][0]=max(ans.a[0][0],-inf);ans.a[0][1]=max(ans.a[0][1],-inf);ans.a[1][0]=max(ans.a[1][0],-inf);ans.a[1][1]=max(ans.a[1][1],-inf);return ans;
}
void swap(node&a){swap(a.a[0][1],a.a[1][0]),swap(a.in[0],a.out[0]),swap(a.in[1],a.out[1]);}
class Segment_Tree{
private:node t[maxn*4];void push_up(int u){t[u]=merge(t[u<<1],t[u<<1|1]);}void update(int u,int l,int r,int d,string z){if(l>d||r<d) return ;if(l==r){t[u].a[0][0]=t[u].a[0][1]=t[u].a[1][0]=t[u].a[1][1]=-inf;if(z[0]=='.') t[u].a[0][0]=1;if(z[1]=='.') t[u].a[1][1]=1;if(z[0]=='.'&&z[1]=='.') t[u].a[0][1]=t[u].a[1][0]=2;t[u].in[0]=max(t[u].a[0][0],t[u].a[0][1]);t[u].in[1]=max(t[u].a[1][0],t[u].a[1][1]);t[u].out[0]=max(t[u].a[0][0],t[u].a[1][0]);t[u].out[1]=max(t[u].a[0][1],t[u].a[1][1]);return ;}int mid=l+r>>1;update(u<<1,l,mid,d,z),update(u<<1|1,mid+1,r,d,z);t[u]=merge(t[u<<1],t[u<<1|1]);}node query(int u,int l,int r,int ll,int rr){if(ll<=l&&r<=rr) return t[u];if(l>rr||r<ll) return node();int mid=l+r>>1;if(rr<=mid) return query(u<<1,l,mid,ll,rr);if(ll>mid) return query(u<<1|1,mid+1,r,ll,rr);return merge(query(u<<1,l,mid,ll,rr),query(u<<1|1,mid+1,r,ll,rr));}
public:void update(int d,string z){update(1,1,n,d,z);}node query(int l,int r){return query(1,1,n,l,r);}
}t;
namespace HLD{int dfn[maxn],cnt_dfn,son[maxn],sz[maxn],fa[maxn],deep[maxn],top[maxn];void dfs(int u){sz[u]=1;deep[u]=deep[fa[u]]+1;for(int v:e[u]){if(v==fa[u]) continue;fa[v]=u;dfs(v);sz[u]+=sz[v];if(sz[v]>sz[son[u]]) son[u]=v;}}void dfs2(int u,int nwtop){top[u]=nwtop;dfn[u]=++cnt_dfn;if(son[u]) dfs2(son[u],nwtop);for(int v:e[u]) if(v!=fa[u]&&v!=son[u]) dfs2(v,v);}void build(){dfs(1);dfs2(1,1);}void update(int u,string s){t.update(dfn[u],s);}int query(int u,int v){node ansu,ansv;ansu.a[0][0]=ansv.a[0][0]=-1;while(top[u]!=top[v]){if(deep[top[u]]<deep[top[v]]){node nw=t.query(dfn[top[v]],dfn[v]);if(~ansv.a[0][0]) ansv=merge(nw,ansv);else ansv=nw;v=fa[top[v]];}else{node nw=t.query(dfn[top[u]],dfn[u]);swap(nw);if(~ansu.a[0][0]) ansu=merge(ansu,nw);else ansu=nw;u=fa[top[u]];}}if(deep[u]<deep[v]){node nw=t.query(dfn[u],dfn[v]);if(~ansv.a[0][0]) ansv=merge(nw,ansv);else ansv=nw;}else{node nw=t.query(dfn[v],dfn[u]);swap(nw);if(~ansu.a[0][0]) ansu=merge(ansu,nw);else ansu=nw;}node ans;if(ansu.a[0][0]==-1) ans=ansv;else if(ansv.a[0][0]==-1) ans=ansu;else ans=merge(ansu,ansv);return max({ans.in[0],ans.in[1],0});}
};
signed main(){read(n,m);for(int i=1;i<n;i++){int u,v;read(u,v);e[u].push_back(v),e[v].push_back(u);}HLD::build();for(int i=1;i<=n;i++){string s;read(s);HLD::update(i,s);}for(int i=1;i<=m;i++){char op;int u,v;string s;read(op,u);if(op=='C') read(s),HLD::update(u,s);else read(v),write(HLD::query(u,v)),write("\n");}return 0;
}
http://www.zskr.cn/news/1350389.html

相关文章:

  • Colab深度学习性能优化实战:从数据加载到模型编译的全链路调优
  • Codex客户端报错无法设置管理员沙盒?一篇文章解决
  • 【ElevenLabs未成年模式深度拆解】:从声纹特征提取到情感倾向干预,技术团队不愿公开的7层过滤逻辑
  • Sora 2人物锚定失效紧急修复手册:3分钟定位tracklet断裂点,5行代码注入Identity Persistence Layer
  • 大模型MoE架构揭秘:稀疏激活与专家路由原理
  • 青海携途国际旅行社服务标准(2026年5月最新,含标准化流程与个旅行团价格) - 寻茫精选
  • 【基础知识】Python入门:元组
  • AI安全中的门控发布机制:原理、实践与技术边界
  • FModel终极指南:掌握虚幻引擎资源逆向工程的完整解决方案
  • 手写K-means聚类:从欧氏距离、质心更新到收敛判断的完整实现
  • 【Elasticsearch从入门到精通】第06篇:Elasticsearch重要系统参数设置——防止启动检查失败
  • 校招数据EDA与分类建模实战:从简历混沌中识别能力信号
  • 通过Taotoken的CLI工具一键配置Python开发环境
  • 3种终极方法破解Navicat Mac版试用限制:一键无限重置教程
  • KAG增强生成、AlphaMath推理与Offloading协同架构
  • Python机器学习实战路线图:从EDA到模型部署的工业级路径
  • 云飞云 + SolidWorks服务器 = 10人研发共享方案,附硬件配置清单
  • 广州搬家公司哪家好:大黄蜂搬家品质上乘 - 17329971652
  • Java 中 ArrayDeque 与 LinkedList 作为栈使用的性能对比
  • 原神抽卡数据分析神器:告别盲目抽卡,用数据掌控你的欧皇之路
  • SolidWorks服务器 + 云飞云共享云桌面,10人研发团队最省钱共享方案
  • Windows热键冲突智能诊断:Hotkey Detective技术深度解析
  • 靠谱的 x 光机厂家推荐:多科智能装备有限公司诚信为本 - 13425704091
  • Mythos能力抽象层:Anthropic的可验证AI推理架构解析
  • 近半数专业人士担忧AI低质量内容,企业领导者支招:重新思考生产力与坚持不懈
  • 用随机森林实现手写大写字母识别的完整实践
  • 如何快速配置FanControl风扇控制:从安装到优化的完整指南
  • 用随机森林实现手写英文字母识别(Python实战)
  • vue3+python基于 Python 的教育机构题包综合任务分配处理系统的设计与实现463050110
  • 如何通过本地解析技术提升网盘下载体验:LinkSwift 的完整解决方案