题目描述
你现在有一个数组 AA
我们定义如下的两种操作:
1. 修改: 形如 00 ll rr ,效果为对所有 l<=i<=rl<=i<=r 执行 Ai+=(i−l+1)Ai+=(i−l+1)
直观地说就是Al+=1,Al+1+=2,Al+2+=3 ... Ar+=r−l+1Al+=1,Al+1+=2,Al+2+=3 ... Ar+=r−l+1 这个样子
2. 查询: 形如 11 ll rr , 要求输出此时的 ∑ri=lAi∑i=lrAi 的值
一开始当然整个数组都是0啦
输入描述
第一行一个整数Q表示操作总数
接下来Q行, 每行一个操作(格式参考题目描述)
输出描述
对于每个查询, 输出一行, 表示此时的 ∑ri=lAi∑i=lrAi 的值
样例输入
3 0 1 2 0 3 4 1 1 4
样例输出
6
数据范围
1<=Q,l,r<=105
最近给学弟学妹讲线段树,发现以前这道题并没有补,就给补上了。
对于一个区间每个位置要加上对应的数 [1 2 3 4 5 6 ...]
若把上述区间分成左右区间就变成了 [1 2 3] [4 5 6]
a b
由于 [4 5 6] = [1 2 3] + [3 3 3]
所以需要两个懒惰标记,lazy1记录这个区间里有多少个等差数列(a部分),lazy2记录这个区间的每个数要加上多少(b部分)
代码如下:
#include<bits/stdc++.h>
#define N 100010
#define ll long long
using namespace std;
struct node
{
int op,l,r;
}eg[N];
ll Sum[N<<2],lazy1[N<<2],lazy2[N<<2];
void pushup(int o)
{
Sum[o]=Sum[o<<1]+Sum[o<<1|1];
}
void pushdown(int o,ll len)
{
if(lazy1[o])
{
lazy1[o<<1]+=lazy1[o]; //等差数列个数下传
lazy1[o<<1|1]+=lazy1[o];
ll l1=len-len/2; //左儿子的长度
ll l2=len/2;
lazy2[o<<1]+=lazy2[o];
lazy2[o<<1|1]+=lazy2[o]+l1*lazy1[o]; //不仅要下传lazy2,还要下传 lazy1个等差数列的前半部分
Sum[o<<1]+=(lazy1[o]*(l1+1)*l1/2)+lazy2[o]*l1;
Sum[o<<1|1]+=(lazy1[o]*(l2+1)*l2/2)+(lazy2[o]+l1*lazy1[o])*l2;
lazy1[o]=lazy2[o]=0;
}
}
void update(int x,int y,int l,int r,int o)
{
if(l>=x&&r<=y)
{
ll len=(ll)(r-l+1);
ll front_len=(ll)l-x; // 因为l>=x的 所以是把[l,r]当作:[1,2,3,..len] + [front_len,front_len,front_len ...front_len]
Sum[o]+=((len+1)*len)/2+len*front_len;
lazy1[o]++;
lazy2[o]+=front_len;
return ;
}
pushdown(o,(ll)r-l+1);
int mid=(l+r)>>1;
if(x<=mid)update(x,y,l,mid,o<<1);
if(y>mid)update(x,y,mid+1,r,o<<1|1);
pushup(o);
}
ll query(int x,int y,int l,int r,int o)
{
if(l>=x&&r<=y)return Sum[o];
pushdown(o,(ll)r-l+1);
int mid=(l+r)>>1;
ll sum=0;
if(x<=mid)sum+=query(x,y,l,mid,o<<1);
if(y>mid)sum+=query(x,y,mid+1,r,o<<1|1);
return sum;
}
int main()
{
int q;
scanf("%d",&q);
int n=0;
for(int i=0;i<q;i++)
{
scanf("%d%d%d",&eg[i].op,&eg[i].l,&eg[i].r);
if(eg[i].l>eg[i].r)swap(eg[i].l,eg[i].r);
n=max(n,eg[i].r);
}
for(int i=0;i<q;i++)
{
if(eg[i].op==0)update(eg[i].l,eg[i].r,1,n,1);
else printf("%lld\n",query(eg[i].l,eg[i].r,1,n,1));
}
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容