#501. 【线段树模板题】序列操作1
操作1:单点替换
操作2:求区间最大值
单点替换不用写tag炒鸡开森
单点替换
void tinsert(int p,int l,int r)
{
if (r<k1 || k1<l) return;
if (l==r)
{
nodes[p]=k2;//替换
return;
}
int mid=(l+r)>>1;
tinsert(p<<1,l,mid);
tinsert(p<<1|1,mid+1,r);
nodes[p]=max(nodes[p<<1],nodes[p<<1|1]);//更新
}
区间查询最大值
int tquery(int p,int l,int r)
{
if (r<k1 || k2<l) return -1;
if (k1<=l && k2>=r) return nodes[p];
int mid=(l+r)>>1;
return max(tquery(p<<1,l,mid),tquery(p<<1|1,mid+1,r));//递归求最值
}
#502. 【线段树模板题】序列操作2
操作1:区间+1
操作2:求区间最大值
这个比501稍微复杂一点,需要用到加法标记
丑陋区间+1
void tinsert(int p,int l,int r)
{
if (r<k1 || k2<l) return;
if (k1<=l && k2>=r)
{
nodes[p].tag++;//标记
nodes[p].ma++;
return;
}
nodes[p*2].ma+=nodes[p].tag;
nodes[p*2+1].ma+=nodes[p].tag;
nodes[p*2].tag+=nodes[p].tag;
nodes[p*2+1].tag+=nodes[p].tag;
nodes[p].tag=0;//pushdown过程
int mid=(l+r)>>1;
tinsert(p<<1,l,mid);
tinsert(p<<1|1,mid+1,r);
nodes[p].ma=max(nodes[p<<1].ma,nodes[p<<1|1].ma);//更新
}
丑陋区间查询最大值
int tquery(int p,int l,int r)
{
if (r<k1 || k2<l) return -1;
if (k1<=l && k2>=r) return nodes[p].ma;
nodes[p*2].ma+=nodes[p].tag;
nodes[p*2+1].ma+=nodes[p].tag;
nodes[p*2].tag+=nodes[p].tag;
nodes[p*2+1].tag+=nodes[p].tag;
nodes[p].tag=0;//pushdown过程
int mid=(l+r)>>1;
return max(tquery(p<<1,l,mid),tquery(p<<1|1,mid+1,r));//递归求最值
}
luogu3373 维护序列
操作1:区间*c
操作2:区间+c
操作3:查询区间和%p
这个要写两个标记,要注意标记的处理
而且一定要记得到处%p
pushdown
void pushdown(int q,int len)
{
long long mul=t[q].mul;
long long add=t[q].add;
t[q<<1].sum=(t[q<<1].sum*mul+add*(len-(len>>1)))%p;
t[q<<1|1].sum=(t[q<<1|1].sum*mul+add*(len>>1))%p;
t[q<<1].add=(t[q<<1].add*mul+add)%p;
t[q<<1|1].add=(t[q<<1|1].add*mul+add)%p;
t[q<<1].mul=(t[q<<1].mul*mul)%p;
t[q<<1|1].mul=(t[q<<1|1].mul*mul)%p;
t[q].add=0;
t[q].mul=1;
return;
}
建树
void build(int q,int l,int r)
{
t[q].add=0;
t[q].mul=1;
if (l==r)
{
t[q].sum=a[l];
return;
}
int mid=(l+r)>>1;
build(q<<1,l,mid);
build(q<<1|1,mid+1,r);
t[q].sum=(t[q<<1].sum+t[q<<1|1].sum)%p;
return;
}
区间*c
void mull(int q,int l,int r)
{
if (x<=l && r<=y)
{
t[q].mul=(t[q].mul*c)%p;
t[q].add=(t[q].add*c)%p;
t[q].sum=(t[q].sum*c)%p;
return;
}
pushdown(q,r-l+1);
int mid=(l+r)>>1;
if (x<=mid)
mull(q<<1,l,mid);
if (y>mid)
mull(q<<1|1,mid+1,r);
t[q].sum=(t[q<<1].sum+t[q<<1|1].sum)%p;
return;
}
区间+c
void addd(int q,int l,int r)
{
if (x<=l && y>=r)
{
t[q].add=(t[q].add+c)%p;
t[q].sum=(t[q].sum+c*(r-l+1))%p;
return;
}
pushdown(q,r-l+1);
int mid=(l+r)>>1;
if (x<=mid)
addd(q<<1,l,mid);
if (y>mid)
addd(q<<1|1,mid+1,r);
t[q].sum=(t[q<<1].sum+t[q<<1|1].sum)%p;
return;
}
查询区间和%p
long long query(int q,int l,int r)
{
if (x<=l && y>=r)
{
return t[q].sum%p;
}
long long temp=0;
int mid=(l+r)>>1;
pushdown(q,r-l+1);
if (x<=mid)
temp=(temp+query(q<<1,l,mid))%p;
if (y>mid)
temp=(temp+query(q<<1|1,mid+1,r))%p;
return temp%p;//其实好像不用模来着
}
修改完一定要return!!!
修改完一定要return!!!
修改完一定要return!!!
重要的话说三遍