This way
现在有n个操作,有两种操作:
1 l r 查看l-r区间所有数是否相同
2 l r a b 区间l-r第i个位置加上a+(i-l)*b
这种题目遇到好几次了,估计下次就懒得写题解。首先区间问题考虑线段树,但是无法直接更新,因为值会随位置变化而变化,怎么解决这个问题,可以在第i个位置上维护 a i − a i − 1 a_i-a_{i-1} ai−ai−1,那么相当于l+1到r的区间+b即可。然后查询就查l+1到r的区间最大最小值是否都为0.注意一点,2操作需要在r+1的位置上-(a+(r-l)*b)
#include
using namespace std;
#define ll long long
#define pa pair
const int N=4e5+5;
ll mx[N*4],mi[N*4],f[N*4];
void push_down(int root){
if(!f[root])
return ;
mx[root<<1]+=f[root];
mx[root<<1|1]+=f[root];
mi[root<<1]+=f[root];
mi[root<<1|1]+=f[root];
f[root<<1]+=f[root];
f[root<<1|1]+=f[root];
f[root]=0;
}
void update(int l,int r,int root,int ql,int qr,ll v){
if(l>=ql&&r<=qr){
mi[root]+=v;
mx[root]+=v;
f[root]+=v;
return ;
}
int mid=l+r>>1;
push_down(root);
if(mid>=ql)
update(l,mid,root<<1,ql,qr,v);
if(mid<qr)
update(mid+1,r,root<<1|1,ql,qr,v);
mx[root]=max(mx[root<<1],mx[root<<1|1]);
mi[root]=min(mi[root<<1],mi[root<<1|1]);
}
pa query(int l,int r,int root,int ql,int qr){
if(l>=ql&&r<=qr)
return {mx[root],mi[root]};
int mid=l+r>>1;
push_down(root);
pa ans={0,0};
if(mid>=ql)
ans=query(l,mid,root<<1,ql,qr);
if(mid<qr){
pa aa=query(mid+1,r,root<<1|1,ql,qr);
ans.first=max(ans.first,aa.first);
ans.second=min(ans.second,aa.second);
}
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
while(m--){
int op,l,r;
ll a,b;
scanf("%d%d%d",&op,&l,&r);
if(op==1){
if(l==r)
printf("1\n");
else{
pa ans=query(1,n,1,l+1,r);
printf("%d\n",ans.first==0&&ans.second==0);
}
}
else{
scanf("%lld%lld",&a,&b);
update(1,n,1,l,l,a);
if(l<r)
update(1,n,1,l+1,r,b);
if(r<n)
update(1,n,1,r+1,r+1,-(a+(r-l)*b));
}
}
return 0;
}
//