离散化
int a[N];
vectortmp;
for(int i=0;i
#include
#include
#include
using namespace std;
int tree[500010],rank[500010],n;
long long ans;
struct point
{
int num,val;
}a[500010];
inline bool cmp(point q,point w)
{
if(q.val==w.val)
return q.num
树状数组
void add(int p, int x){ //给位置p增加x
while(p <= n) sum[p] += x, p += p & -p;
}
int ask(int p){ //求位置p的前缀和
int res = 0;
while(p) res += sum[p], p -= p & -p;
return res;
}
int range_ask(int l, int r){ //区间求和
return ask(r) - ask(l - 1);
}
线段树
#include
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+5;
struct tree{
int l,r;
ll val,add;
}t[maxn*4];
ll a[maxn];
// 建树
void build(int p,int l,int r)
{ // 以p为编号的节点维护的区间为l到r
t[p].l=l;t[p].r=r;
if(l==r)
{
t[p].val=a[l];
return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
t[p].val=t[p<<1].val+t[p<<1|1].val;
}
void spread(int p)
{ // 如果懒标记不为0,就将其下传,修改左右儿子维护的值
if(t[p].add)
{
// 修改val:在区间查询要用到
t[p<<1].val += t[p].add*(t[p<<1].r-t[p<<1].l+1);
t[p<<1|1].val += t[p].add*(t[p<<1|1].r-t[p<<1|1].l+1);
t[p<<1].add += t[p].add;
t[p<<1|1].add += t[p].add;
t[p].add=0; // 下传之后将该节点的懒标记清0
}
}
// 区间修改
void change(int p,int x,int y,ll z)
{ //修改的区间覆盖了当前节点时,我们就把这个区间给修改,并打上懒标记
if(x<=t[p].l && y>=t[p].r)
{
t[p].val += z*(t[p].r-t[p].l+1);
t[p].add += z;
return ;
}
spread(p); // 到这里是没有覆盖的,所以要标记下放
int mid=(t[p].l+t[p].r)>>1;
if(x<=mid) change(p<<1,x,y,z);//如果要修改的区间覆盖了左儿子,就修改左儿子
if(y>=mid+1) change(p<<1|1,x,y,z);
t[p].val = t[p<<1].val + t[p<<1|1].val;
}
//区间查询
ll ask(int p,int x,int y)
{
if(x<=t[p].l && y>=t[p].r) return t[p].val; //恰好覆盖
spread(p);
int mid=(t[p].l+t[p].r)>>1;
ll ans=0;
if(x<=mid) ans += ask(p<<1,x,y);
if(y>=mid+1) ans += ask(p<<1|1,x,y);
return ans;
}
void show()
{
for(int p=1;t[p].val>0;p++)
{
printf("(%d %d) val=%d add=%d\n",t[p].l,t[p].r,t[p].val,
t[p].add);
}
puts("");
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
while(m--)
{
ll q,x,y,k;
cin>>q>>x>>y;
if(q==1)
{
cin>>k;
change(1,x,y,k);
}
else
{
cout<