题意
给出个数的数列,有
个操作,操作涉及到区间加法和求区间前驱(小于
的最大值)
思路
区间加法还是跟前几题一样用数组标记,同入门2求小于
的个数,那么我们还是将每一块进行排序,然后用二分的方法去查找,这样的时间复杂度并不高。
代码
#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int N = 100007;
int l[N],r[N],block,num,belong[N],n,x,y;
ll a[N],lazy[N],b[N];
inline void build()
{
block=sqrt(n);
num=n/block;if (n%num) num++;
for (int i=1;i<=num;i++)
l[i]=(i-1)*block+1,r[i]=i*block;
r[num]=n;
for (int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
for (int i=1;i<=num;i++)
sort(b+l[i],b+r[i]+1);
}
inline void update(int x,int y,int c)
{
if (belong[x]==belong[y])
{
for (int i=x;i<=y;i++) a[i]+=c;
for (int i=l[belong[x]];i<=r[belong[x]];i++) b[i]=a[i];
sort(b+l[belong[x]],b+r[belong[x]]+1);
return;
}
for (int i=x;i<=r[belong[x]];i++) a[i]+=c;
for (int i=l[belong[x]];i<=r[belong[x]];i++) b[i]=a[i];
sort(b+l[belong[x]],b+r[belong[x]]+1);
for (int i=belong[x]+1;i<belong[y];i++) lazy[i]+=c;
for (int i=l[belong[y]];i<=y;i++) a[i]+=c;
for (int i=l[belong[y]];i<=r[belong[y]];i++) b[i]=a[i];
sort(b+l[belong[y]],b+r[belong[y]]+1);
//以上同入门2
//教训:b[i]复制一定要整块复制
}
inline ll ask(int x,int y,ll c)
{
int cnt=0,ans=-1;
if (belong[x]==belong[y])
{
for (int i=x;i<=y;i++)
if (a[i]+lazy[belong[x]]<c&&a[i]+lazy[belong[x]]>ans)
ans=a[i]+lazy[belong[x]];
return ans;
}
for (int i=x;i<=r[belong[x]];i++)
if (a[i]+lazy[belong[x]]<c&&a[i]+lazy[belong[x]]>ans)
ans=a[i]+lazy[belong[x]];
for (int i=l[belong[y]];i<=y;i++)
if (a[i]+lazy[belong[y]]<c&&a[i]+lazy[belong[y]]>ans)
ans=a[i]+lazy[belong[y]];
//不完整块暴力求解
for (int i=belong[x]+1;i<belong[y];i++)
{
int t=lower_bound(b+l[i],b+r[i]+1,c-lazy[i])-(b+l[i]);
if (t==0) continue;
int tmp=t+l[i]-1;
//最重要的就是这个tmp,是否-1,还是+1,还是加上l[i]
//int tmp=t+(i-1)*blcok
if (b[tmp]+lazy[i]<c&&b[tmp]+lazy[i]>ans) ans=b[tmp]+lazy[i];
}
return ans;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
IOS
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
}
build();
for (int k=1;k<=n;k++)
{
int l,r,op;
ll c;
cin>>op>>l>>r>>c;
if (op==0)
update(l,r,c);
else
cout<<ask(l,r,c)<<endl;
}
return 0;
}