Zxx20120715 @ 2024-05-22 18:41:45
#include<iostream>
using namespace std;
const int maxn=100010;
int n,m,a[maxn];
struct node//线段树的一个节点
{
//第一个需要修改的地方:增加维护的值
int l,r;//这段区间的左端点、右端点
int sum;//这段区间的和
int minv;//这段区间的最小值
int tag;//懒标记
//代表当前节点所对应的区间 每一个数都被加了tag
//但是 这件事还没有告诉当前节点的两个儿子
node(){
//第二个需要修改的地方:增加维护的值的初始化
l=r=sum=tag=minv=0;
}
}z[maxn*4];//z[i]代表线段树的第i个节点
#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
node operator+(const node &l,const node &r)//定义线段树如何合并两个区间
{
//第三个需要修改的地方:增加维护的值 计算方法
node res;
res.l=l.l; res.r=r.r;
res.sum = l.sum + r.sum;
res.minv = min(l.minv,r.minv);
return res;
}
void build(int l,int r,int rt)//当前的线段树节点编号为rt 其所对应的区间为l~r
//建立这棵线段树
{
if (l==r)//走到了最下面 区间只有一个数 那就建立这个节点
{
//第四个需要修改的地方:长度为1的区间这个值怎么处理
z[rt].l=z[rt].r=l;
z[rt].sum = a[l];
z[rt].minv=a[l];
return;
}
int m=(l+r)>>1;//从l~r中间砍开 l~m作为左儿子区间 m+1~r作为右儿子区间
build(lson);//build(l,m,rt<<1);//build(l,m,rt*2);//建立左儿子
build(rson);//build(m+1,r,rt<<1|1);//build(m+1,r,rt*2+1);//建立右儿子
z[rt] = z[rt<<1] + z[rt<<1|1];
}
void color(int rt,int v)//给节点rt打一个+v的懒标记
{
//第五个需要修改的地方:增加维护的值的打标记方法
z[rt].sum += v * (z[rt].r-z[rt].l+1);
z[rt].tag += v;
z[rt].minv += v;
}
void push_col(int rt)//把节点rt的标记告诉它的儿子
{
if (z[rt].tag != 0)
{
color(rt<<1,z[rt].tag);
color(rt<<1|1,z[rt].tag);
z[rt].tag=0;
}
}
node query(int l,int r,int rt,int nowl,int nowr)//logn
//当前线段树节点为l~r,编号为rt 此时要询问nowl~nowr这段区间
{
if (nowl<=l && r<=nowr) return z[rt];//l~r当前线段树节点所对应的区间被询问区间完全包含
push_col(rt);//把懒标记下放
int m=(l+r)>>1;
if (nowl<=m)//询问区间和左儿子有交
{
if (m<nowr)//询问区间和右儿子有交
return query(lson,nowl,nowr) + query(rson,nowl,nowr);
else//代表只和左儿子有交
return query(lson,nowl,nowr);
}
else//只和右儿子有交
return query(rson,nowl,nowr);
}
void modify(int l,int r,int rt,int nowl,int nowr,int v)
//当前线段树节点编号为rt 区间为l~r
//修改操作为给nowl~nowr这段区间整体+v
{
if (nowl<=l && r<=nowr) {//当前区间被修改区间整体包含
color(rt,v);//给节点rt打一个整体+v的懒标记
return;
}
push_col(rt);//把懒标记下放
int m=(l+r)>>1;
if (nowl<=m) modify(lson,nowl,nowr,v);//修改区间和左儿子有交
if (m<nowr) modify(rson,nowl,nowr,v);//修改区间和右儿子有交
z[rt] = z[rt<<1] + z[rt<<1|1];
}
int main()
{
cin >> n >> m;
for (int i=1;i<=n;i++)
cin >> a[i];
build(root);//建树
for (int i=1;i<=m;i++)
{
int opt;
cin >> opt;
if (opt==1)//修改操作
{
int x,y,k;
cin >> x >> y >> k;
modify(root,x,y,k);
}
else//询问操作
{
int x,y;
cin >> x >> y;
cout << query(root,x,y).sum << endl;
}
}
return 0;
}
这位蒟蒻在 #8 #9 #10 WA,求助。
by 迟暮天复明 @ 2024-05-22 19:01:32
兄弟你没开ll
by Zxx20120715 @ 2024-05-22 19:07:45
@迟暮天复明 已 AC 十分感谢!