Interpretation \color{green}{\texttt{Interpretation}} Interpretation

吉司机线段树(A.K.A. 势能线段树),个人觉得,就是对普通线段树的一种优化技巧。这种优化技巧有点像搜索算法里面的剪枝。

在普通线段树中,为了避免一次区间操作浪费太多时间,我们利用了一种叫作懒标记Lazy Tag)的技巧。懒标记的核心是利用操作的可合并性,当进行操作时,先在根节点上进行标记,需要访问子节点时再把标记下放。

但是,对于一些没有可合并性的操作(比如开平方等),懒标记就不适用了。

但是,既然题目出出来了,就应该有方法解,这类型的题目的操作大多有一个共同点:操作次数比较有限。

比如 开平方并向下取整 操作,哪怕是一个很大的数,通过有限次操作( 64 64 64 位正整数好像最多只需要 25 25 25 次吧,不记得了)就可以使它变成 1 1 1,然后操作就失效了(再操作也还是 1 1 1)。

我们可以想象有这些数本身就有一定的某种“势能”,而每次操作都会使得这个“势能”降低,知道达到最低(即使操作失效)。

我们可以记录下这个“势能”,然后进行区间修改时,先判断这个区间的最高“势能”是否已经达到了最低,如果是,那么这个操作对于这个区间而言就失效了,可以退出操作。

如果“势能”下降的速度足够开,就可以使时间复杂度降低到可以承受的范围。

比如对于那个 开平方并向下取整 的操作来说,我们就记录下每个区间的最大值,如果某个区间的最大值已经是 1 1 1 了,那么进行操作时就可以忽视这个区间。

Example - Hdu 7059 \color{green}{\texttt{Example - Hdu 7059}} Example - Hdu 7059

[Problem] \color{blue}{\texttt{[Problem]}} [Problem]

给定长度为 n n n 的数列 a 1.. n a_{1 .. n} a1..n​,三种操作:

  1. 求区间和
  2. 将区间内的所有数减去它的 lowbit
  3. 将区间内的所有数加上它的 highbit

[Analysis] \color{blue}{\texttt{[Analysis]}} [Analysis]

不是很显然的,我们知道,操作 2 2 2 会使每个数二进制下 1 1 1 的个数减少 1 1 1,而操作 3 3 3 不会影响每个数二进制下 1 1 1 的个数。

于是可以使用吉司机线段树,“势能”就是每个数二进制下 1 1 1 的个数。

代码很简单。

[code] \color{blue}{\texttt{[code]}} [code]

inline int lowbit(int x){return (x&(-x));
}
inline int highbit(int x){for(int i=30;i>=0;i--)if ((x>>i)&1) return (1<<i);
}
inline int CountBit(int x){int ret=0;for(int i=30;i>=0;i--)if ((x>>i)&1) ret++;return ret;
}const int mod=998244353;
const int N=1e5+100,M=N<<1;int n,m,a[N],Pow[N];int rt,ncnt,ls[M],rs[M];
int hb[M],lb[M],cnt[M],tag[M];inline void init(int o){ls[o]=rs[o]=hb[o]=lb[o]=cnt[o]=tag[o]=0;
}inline void pushup(int o){hb[o]=(hb[ls[o]]+hb[rs[o]])%mod;lb[o]=(lb[ls[o]]+lb[rs[o]])%mod;cnt[o]=max(cnt[ls[o]],cnt[rs[o]]);
}
inline void pushdown(int o){tag[ls[o]]+=tag[o];tag[rs[o]]+=tag[o];hb[ls[o]]=1ll*hb[ls[o]]*Pow[tag[o]]%mod;hb[rs[o]]=1ll*hb[rs[o]]*Pow[tag[o]]%mod;tag[o]=0;return;
}
void build(int &o,int l,int r){init(o=++ncnt);if (l==r){hb[o]=highbit(a[l]);lb[o]=a[l]-hb[o];cnt[o]=CountBit(a[l]);return;}int mid=(l+r)>>1;build(ls[o],l,mid);build(rs[o],mid+1,r);pushup(o);return;
}
void modify(int o,int l,int r,int p,int q){if (cnt[o]==0) return;if (l==r){if (cnt[o]>1){lb[o]-=lowbit(lb[o]);cnt[o]--;}else hb[o]=cnt[o]=0;return;}if (tag[o]) pushdown(o);int mid=(l+r)>>1;if (p<=mid) modify(ls[o],l,mid,p,q);if (mid<q) modify(rs[o],mid+1,r,p,q);pushup(o);return;
}
void update(int o,int l,int r,int p,int q){if (cnt[o]==0) return;if (p<=l&&r<=q){hb[o]=2ll*hb[o]%mod;tag[o]++;return;}if (tag[o]) pushdown(o);int mid=(l+r)>>1;if (p<=mid) update(ls[o],l,mid,p,q);if (mid<q) update(rs[o],mid+1,r,p,q);pushup(o);return;
}
int query(int o,int l,int r,int p,int q){if (cnt[o]==0) return 0;if (p<=l&&r<=q) return (hb[o]+lb[o])%mod;if (tag[o]) pushdown(o);int mid=(l+r)>>1,ans=0;if (p<=mid) ans=(ans+query(ls[o],l,mid,p,q))%mod;if (mid<q) ans=(ans+query(rs[o],mid+1,r,p,q))%mod;return ans;
}int main(){Pow[0]=1;for(int i=1;i<=1e5;i++)Pow[i]=2ll*Pow[i-1]%mod;for(int T=1,Q=read();T<=Q;T++){n=read();for(int i=1;i<=n;i++)a[i]=read();ncnt=0;rt=0;build(rt,1,n);m=read();for(int i=1;i<=m;i++){int opt=read(),l=read(),r=read();if (opt==1) printf("%d\n",query(rt,1,n,l,r));else if (opt==2) modify(rt,1,n,l,r);else update(rt,1,n,l,r);}}return 0;
}

Reference \color{green}{\texttt{Reference}} Reference

https://blog.csdn.net/jibinquan/article/details/120597782

2022.08.21 吉司机线段树略讲相关推荐

  1. 势能线段树/吉司机线段树-我没有脑子

    势能线段树/吉司机线段树 BZOJ3211 花神游历各国 BZOJ5312 冒险 BZOJ4355 Play with sequence BZOJ4695 最假女选手 \(A_i = max(A_i, ...

  2. 2020ICPC(南京) - Just Another Game of Stones(吉司机线段树+博弈)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的数列 aaa,现在需要执行 mmm 次操作,每次操作分为两种类型: 1lrx1 \ l \ r \ x1 l r x:对于所有 i∈[l,r]i ...

  3. HDU - 5306 Gorgeous Sequence(吉司机线段树)

    题目链接:点击查看 题目大意:给出 1 ~ n 的区间以及 m 次操作,每次操作分为三种形式: 0 l r val:对于区间 [ l , r ] ,a[ i ] = min ( a[ i ] , va ...

  4. P6242-[模板]线段树3【吉司机线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P6242 题目大意 给出一个长度为nnn的序列aaa,mmm次要求支持操作 区间加上一个值kkk 区间所有aia_i ...

  5. P7560-[JOISC 2021 Day1]フードコート【吉司机线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P7560 题目大意 有 n n n个队列,要求支持操作: 往 [ L , R ] [L,R] [L,R]的队列中插入 ...

  6. 势能线段树(吉司机线段树)专题

    势能线段树(吉司机线段树)专题 势能线段树在近期训练时遇到了好几次,但是由于本人太懒一直没补完,结果ICPC网络赛还真就出了一道势能线段树Orz--结果当然是没做出来--痛定思痛,这回把之前欠的一块儿 ...

  7. 【模板】吉老师线段树

    ACM模板 目录 区间取最值 区间取最值 Gorgeous Sequence 区间最值操作往往采用以下办法 线段树维护: 区间最大值mx\text{mx}mx 区间严格次大值smx\text {smx ...

  8. 2022/08/15 吉软 MySQL数据库(1)

    目录 一.数据库: 二.SQL 2.1.SQL的优点 2.2.SQL的分类 2.2.1.DCL(数据控制语言) 2.2.2.DDL(数据定义语言) 2.2.3.DML(数据操作语言) 三.MySQL: ...

  9. 2022/08/27 吉软 Vue

    目录 Vue前言 概述: 特点: 一. Vue导入 概述: 语法: 基本使用: 二.Vue基本语法 1.插值表达式 概述: 2.显示数据(v-text和v-html) 概述: 语法: 区别: 3.数据 ...

最新文章

  1. 济南python工资一般多少钱-马哥教育官网-专业Linux培训班,Python培训机构
  2. python批量读取grib_windows python读取grib2数据
  3. 简约才是王道? CardView 的使用
  4. 八皇后时间复杂度_回溯算法 | 追忆那些年曾难倒我们的八皇后问题
  5. libevent源码学习-----统一事件源及信号绑定函数
  6. spring和activemq的结合(五)
  7. 【分析】1021 Deepest Root (25 分)【DFS解法】
  8. Linux嵌入式入门
  9. treeSet中对象的比较
  10. 问答| 在四轮驱动机器人(SSMR)运动学模型中,左右虚拟轮的线速度vl和vr如何得到?
  11. Struts2 初探
  12. 如何让客户接受你的价格比别人更高?
  13. 与rasp的初次心动
  14. 计算机电缆2x2x1.5,DJYPVP计算机电缆DJYPVP电缆2x2x1.5线缆
  15. 关于微信卡券47001的问题
  16. 【Free5GC】test.sh脚本测试流程
  17. 计算机弹音乐百度百科,音乐术语
  18. org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /
  19. 用 Python 自动生成 Excel 数据报表~
  20. PTA-浙大版《Python 程序设计》AC解答汇总

热门文章

  1. SuperSlide插件的使用方法
  2. 小白勿进!「高并发秒杀」微信抢红包实战案例
  3. 说说团队建设与管理的那些事儿
  4. Amazon Global Accelerator 的新增功能 — 互联网协议版本 6(IPv6)支持
  5. Comparing Dynamics: Deep Neural Networks versus Glassy Systems 读书笔记
  6. TurtleBot3 命令行
  7. Mac 电脑浏览器字体显示异常解决方案
  8. 西天目浙西二日游--游记
  9. python 获取某个字符指定字符的前面、后面和中间的字符
  10. 甲骨文在开源后裁掉了JMC整个团队;中兴:将支付10亿美元罚款,更换董事会等高层;阿里云:未来三年追平亚马逊技术丨Q新闻...