题解 CF145E Lucky Queries

线段树。

在树中我们维护四个东西:最长不下降子序列的长度,最长不上升子序列的长度,4的个数和7的个数。

线段树最重要的是pushup,也就是合并。

显然4的个数和7的个数就直接加一下,没什么好说的。

因为数列中不是4就是7,所以这个最长不下降子序列一定有一个47的分界点。

如果这个分界点在左儿子里,那么父节点的最长不下降子序列的长度就是左儿子的最长不下降子序列长度加上右儿子的7的个数。

如果这个分界点在右儿子里,那么父节点的最长不下降子序列的长度就是左儿子的4的个数加上右儿子的最长不下降子序列长度。

最长不上升子序列的长度同理。

这部分的代码

Copy
struct node { ll l,r,mid,vals,valx,num4,num7;//vals是最长不上升子序列长度,valx是最长不下降子序列长度 bool tag;//lazy标记 }seg[N<<2]; inline void pushup(re ll pos) { seg[pos].vals=max(seg[pos<<1].vals+seg[pos<<1|1].num7,seg[pos<<1].num4+seg[pos<<1|1].vals); seg[pos].valx=max(seg[pos<<1].valx+seg[pos<<1|1].num4,seg[pos<<1].num7+seg[pos<<1|1].valx); seg[pos].num4=seg[pos<<1].num4+seg[pos<<1|1].num4; seg[pos].num7=seg[pos<<1].num7+seg[pos<<1|1].num7; return; }

建树就没什么可说的了,和正常的线段树建树一样,最长不上升子序列长度和最长不下降子序列的长度都赋为1

Copy
inline void build(re ll pos,re ll l,re ll r) { seg[pos].l=l; seg[pos].r=r; seg[pos].mid=l+r>>1; if(l==r) { seg[pos].vals=seg[pos].valx=1; seg[pos].num4=(a[l]==4); seg[pos].num7=(a[l]==7); } else { build(pos<<1,l,seg[pos].mid); build(pos<<1|1,seg[pos].mid+1,r); pushup(pos); } return; }

修改操作就直接把最长不上升子序列的长度和最长不下降子序列的长度交换,4的数量和7的数量交换。

标记下传

Copy
inline void add(re ll pos) { seg[pos].tag^=1; swap(seg[pos].num4,seg[pos].num7); swap(seg[pos].valx,seg[pos].vals); return; } inline void pushdown(re ll pos) { if(!seg[pos].tag) return; add(pos<<1); add(pos<<1|1); seg[pos].tag^=1; return; }

区间修改

Copy
inline void upgrade(re ll pos,re ll l,re ll r) { if(seg[pos].l>=l&&seg[pos].r<=r) return add(pos); else if(seg[pos].l>r||seg[pos].r<l) return; pushdown(pos); upgrade(pos<<1,l,r); upgrade(pos<<1|1,l,r); pushup(pos); return; }

每次询问的结果就是seg[1].vals

注意这个毒瘤的没有空格的输入就好了。

posted @   CelticOIer  阅读(75)  评论(1编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示