题解:分块
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 500003
#define LL long long
using namespace std;
int belong[N],l[N],r[N];
LL val[N],delta[N];
struct point
{
LL x; int pos;
};
struct data{
point a[720];
}c[720];
int n,m;
int cmp(point a,point b)
{
return a.x<b.x||a.x==b.x&&a.pos<b.pos;
}
void build(int x)
{
int cnt=0;
for (int i=l[x];i<=r[x];i++) c[x].a[++cnt].x=val[i],c[x].a[cnt].pos=i;
sort(c[x].a+1,c[x].a+cnt+1,cmp);
}
void calc(int &x,int &y,int k,LL v)
{
LL vl=v-delta[k];
if (vl<=0) return;
int ls=1; int rs=r[k]-l[k]+1; int ans=n+1;
while (ls<=rs) {
int mid=(ls+rs)/2;
if (c[k].a[mid].x>=vl) ans=min(ans,mid),rs=mid-1;
else ls=mid+1;
}
if (c[k].a[ans].x==vl&&ans!=n+1)
x=min(x,c[k].a[ans].pos),y=max(y,c[k].a[ans].pos);
ls=1; rs=r[k]-l[k]+1; ans=0;
while (ls<=rs) {
int mid=(ls+rs)/2;
if (c[k].a[mid].x<=vl) ans=max(ans,mid),ls=mid+1;
else rs=mid-1;
}
if (c[k].a[ans].x==vl&&ans!=0)
x=min(x,c[k].a[ans].pos),y=max(y,c[k].a[ans].pos);
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%I64d",&val[i]);
int block=sqrt(n);
int t=ceil(n*1.0/block);
for (int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
for (int i=1;i<=t;i++) l[i]=n,r[i]=0;
for (int i=1;i<=n;i++) {
int k=belong[i];
l[k]=min(i,l[k]);
r[k]=max(r[k],i);
}
for (int i=1;i<=t;i++) build(i);
for (int i=1;i<=m;i++) {
int opt,x,y; LL k;
scanf("%d",&opt);
if (opt==1) {
scanf("%d%d%I64d",&x,&y,&k);
if (belong[x]==belong[y]) {
for (int i=x;i<=y;i++) val[i]+=k;
build(belong[x]); continue;
}
for (int i=x;i<=r[belong[x]];i++) val[i]+=k;
build(belong[x]);
for (int i=l[belong[y]];i<=y;i++) val[i]+=k;
build(belong[y]);
for (int i=belong[x]+1;i<=belong[y]-1;i++) delta[i]+=k;
}
else {
scanf("%I64d",&k);
int x=n+1; int y=0;
for (int i=1;i<=t;i++)
calc(x,y,i,k);
printf("%d\n",max(-1,y-x));
}
}
}