众所周知,sgt十分难写 并且如果模板记错 调试难度也十分大,然而今天我在写树剖的时候突发奇想,我们是否可以用一些数据结构代替线段树?以下是我的一些总结:
1.区间修改单点查询
这个十分简单 基本的查分用树状数组维护就好了
代码实现:略
2.区间修改区间查询
2相比1提高了许多难度,不过2个树状数组依旧是可以解决的,第一个树状树状为S1 第二个为S2,S1维护基本的查分,S2维护di*i 原理如下
显然有如下公式:
ai=∑xi=1
然后得:
∑xi=1ai=∑xi=1∑ij=1di
继续推得:
∑xi=1ai=∑xi=1∗(x−i+1)di
最后化简一下就发现2个数组啦:
∑xi=1ai=∑xi=1(x+1)∗di−∑xi=1di∗i
代码如下啦啦啦:
void add(int x,int y)
{for(int i=x;i<=n;i+=lb(i)) c1[i]+=y,c2[i]+=(long long)x*y;}
long long sum(int x)
{
long long ans(0);
for(int i=x;i;i-=lb(i)) ans+=(x+1)*c1[i]-c2[i];
return ans;
}
我有恶意压行嫌疑 但显然不长不是喵!
3.区间最大最小值
哈!一道RMQ好题!我一般是用ST表写 这里直接上代码吧
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i<=n+1-(1<<j);i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
k=int(log2(r-l+1));
printf("%d\n",max(f[l][k],f[r-(1<<k)+1][k]));
十分简洁啧啧啧 然后我们的线段树就如此被替代了?不然。。。RMQ只能离线。。。。。。。。。。。。。。。。
4.区间乘法!
显然将
∑
换成
∏
就ok了 但是如果乘加交替的话,貌似比较难维护,博主正在辛勤研究ing~~ 好了最后谢谢大家!