终于写对了线段树
今天开始了洛谷春令营,然后我因为昨天晚上肝到太晚,结果…8:28才起床,GG。
之后早饭没吃直接开机听课,还好没耽误。
今天上午首先讲的就是线段树的变种,我连线段树还没打出来呢!!!搞什么变种?!不过以前已经看过并理解了线段树的大体思路,所以听起课来还是没有多大障碍的,至于课程的具体内容,晚些时候发篇密码博客总结一下。
于是今天下午吃过饭就开始敲线段树。
一直敲到现在,中间换了无数本资料+看了无数题解,大概勉强找到了和我期望的线段树差不多的题解,写好之后一句一句对照来检查终于算是完事了,结果一运行,一询问直接无响应,最后被逼无奈输出各种中间值,发现是把一个变量写错了,因为当时题解和我的代码用的变量不一样所以没看出来,GG!!!
debug完成后提交洛谷模板题:P3372 【模板】线段树 1终于AC!有生以来第一次写出了完整的线段树(热泪盈眶)!!!
放一下代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100001,maxm=100001;
long long a[maxn],n,m,x,y,k,mod;
struct node
{
long long sumv[maxn<<2],addv[maxn<<2];
inline void pushup(int o)
{
sumv[o]=sumv[o<<1]+sumv[o<<1|1];
}
inline void pushdown(int o,int l,int r,int s,int t)
{
if(!addv[o])return;
int mid=(l+r)>>1;
sumv[o<<1]+=addv[o]*(mid-l+1);addv[o<<1]+=addv[o];
sumv[o<<1|1]+=addv[o]*(r-mid);addv[o<<1|1]+=addv[o];
addv[o]=0;return;
}
inline void build(int o,int l,int r)
{
if(l==r)
{
sumv[o]=a[l];
return;
}
int mid = (l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
pushup(o);
}
inline void optadd(int o,int l,int r,int s,int t,long long v)
{
if(l>=s&&r<=t)
{
sumv[o]+=v*(r-l+1);
addv[o]+=v;
return;
}
int mid=(l+r)>>1;
pushdown(o,l,r,s,t);
if(s<=mid)optadd(o<<1,l,mid,s,t,v);
if(t>mid)optadd(o<<1|1,mid+1,r,s,t,v);
pushup(o);
}
long long query(int o,int l,int r,int s,int t)
{
if(l>=s&&r<=t)return sumv[o];
long long ans=0;
int mid=(l+r)>>1;
if(addv[o])pushdown(o,l,r,s,t);
if(s<=mid)
{
ans+=query(o<<1,l,mid,s,t);
}
if(t>mid)
{
ans+=query(o<<1|1,mid+1,r,s,t);
}
return ans;
}
}segtree;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
segtree.build(1,1,n);
while(m--)
{
scanf("%d",&k);
if(k==1)
{
scanf("%d%d%d",&x,&y,&k);
segtree.optadd(1,1,n,x,y,k);
}
else
{
scanf("%d%d",&x,&y);
long long ans=segtree.query(1,1,n,x,y);
printf("%lld\n",ans);
}
}
return 0;
}