
做法是存每个区间的最左,最右的值和答案,合并区间的时候判断是否为单调递增
#include<bits/stdc++.h>
#define int long long
const int MAXN=1000005;
using namespace std;
int n,k,a[MAXN];
struct node
{
int ans,l,r,lazy_tag;
}tre[MAXN*4];
inline int ls(int x){return x*2;}
inline int rs(int x){return x*2+1;}
void push_up(int pos)
{
if(tre[ls(pos)].r<=tre[rs(pos)].l&&tre[ls(pos)].ans&&tre[rs(pos)].ans)
tre[pos].ans=1;
else
tre[pos].ans=0;
tre[pos].l=tre[ls(pos)].l;
tre[pos].r=tre[rs(pos)].r;
}
void build(int l,int r,int pos)
{
if(l==r)
{
tre[pos].ans=1;
tre[pos].l=tre[pos].r=a[l];
return ;
}
int mid=(l+r)/2;
build(l,mid,ls(pos));
build(mid+1,r,rs(pos));
push_up(pos);
}
void push_down(int pos)
{
tre[ls(pos)].lazy_tag+=tre[pos].lazy_tag;
tre[rs(pos)].lazy_tag+=tre[pos].lazy_tag;
tre[ls(pos)].l+=tre[pos].lazy_tag;
tre[rs(pos)].r+=tre[pos].lazy_tag;
tre[pos].lazy_tag=0;
}
void update(int dl,int dr,int l,int r,int pos,int x)
{
push_down(pos);
if(dl<=l&&r<=dr)
{
tre[pos].lazy_tag+=x;
tre[pos].l+=x;
tre[pos].r+=x;
return ;
}
int mid=(l+r)/2;
if(dl<=mid)update(dl,dr,l,mid,ls(pos),x);
if(dr>mid)update(dl,dr,mid+1,r,rs(pos),x);
push_up(pos);
}
int query(int dl,int dr,int l,int r,int pos)
{
push_down(pos);
if(dl<=l&&r<=dr)return tre[pos].ans;
int mid=(l+r)/2;
if(dl<=mid&&dr>mid)
{
int s1=query(dl,dr,l,mid,ls(pos));
int s2=query(dl,dr,mid+1,r,rs(pos));
return (s1&&s2&&tre[ls(pos)].r<=tre[rs(pos)].l);
}
if(dl<=mid)return query(dl,dr,l,mid,ls(pos));
if(dr>mid)return query(dl,dr,mid+1,r,rs(pos));
}
signed main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
build(1,n,1);
for(int i=1;i<=k;i++)
{
int op,l,r;
scanf("%lld%lld%lld",&op,&l,&r);
if(r>n)r--;
if(op==1)
{
int x;
scanf("%lld",&x);
update(l,r,1,n,1,x);
}
else
{
if(query(l,r,1,n,1))printf("Yes\n");
else printf("No\n");
}
}
}