题目地址:http://codeforces.com/contest/551/problem/E
将n平均分成sqrt(n)块,对每一块从小到大排序,并设置一个整体偏移量。
修改操作:l~r区间内,对两端的块进行暴力处理,对中间的整体的块用整体偏移量标记增加了多少。时间复杂度: O(2*sqrt(n)+n/sqrt(n)).
查询操作:对每一块二分,查找y-整体偏移量。找到最左边的和最右边的。时间复杂度:O(sqrt(n)*log(sqrt(n)))。
代码如下:
#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
#include <time.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
//#pragma comment(linker, "/STACK:1024000000")
//const int mod=9901;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=500000+10;
LL b[MAXN];
struct node
{
LL x;
int id;
}fei[MAXN];
int BS1(int low, int high, LL x)
{
int mid, ans=-1;
while(low<=high){
mid=low+high>>1;
if(fei[mid].x<=x){
ans=mid;
low=mid+1;
}
else high=mid-1;
}
return ans;
}
int BS2(int low, int high, LL x)
{
int mid, ans=-1;
while(low<=high){
mid=low+high>>1;
if(fei[mid].x>=x){
ans=mid;
high=mid-1;
}
else low=mid+1;
}
return ans;
}
bool cmp(node x, node y)
{
if(x.x==y.x) return x.id<y.id;
return x.x<y.x;
}
int main()
{
int n, q, i, j, l, r, k, min1, max1, z, ll, rr, tmp, tot;
LL y, x;
while(scanf("%d%d",&n,&q)!=EOF){
for(i=0;i<n;i++){
scanf("%I64d",&fei[i].x);
fei[i].id=i;
}
k=sqrt(n*1.0);
tot=(n+k-1)/k;
for(i=0;i<tot;i++){
sort(fei+i*k,fei+min((i+1)*k,n),cmp);
}
memset(b,0,sizeof(b));
while(q--){
scanf("%d",&z);
if(z==1){
scanf("%d%d%I64d",&l,&r,&x);
l--;r--;
ll=l/k;rr=r/k;
for(i=ll*k;i<(ll+1)*k&&i<n;i++){
if(fei[i].id>=l&&fei[i].id<=r){
fei[i].x+=x;
}
}
sort(fei+ll*k,fei+min((ll+1)*k,n),cmp);
if(ll!=rr){
for(i=rr*k;i<n&&i<(rr+1)*k;i++){
if(fei[i].id>=l&&fei[i].id<=r){
fei[i].x+=x;
}
}
sort(fei+rr*k,fei+min((rr+1)*k,n),cmp);
}
for(i=ll+1;i<rr;i++){
b[i]+=x;
}
}
else{
scanf("%I64d",&y);
min1=max1=-1;
for(i=0;i<tot;i++){
tmp=BS2(i*k,min((i+1)*k-1,n-1),y-b[i]);
if(tmp!=-1&&fei[tmp].x==y-b[i]){
min1=fei[tmp].id;
break;
}
}
for(i=tot-1;i>=0;i--){
tmp=BS1(i*k,min((i+1)*k-1,n-1),y-b[i]);
if(tmp!=-1&&fei[tmp].x==y-b[i]){
max1=fei[tmp].id;
break;
}
}
if(min1==-1&&max1==-1){
puts("-1");
}
else printf("%d\n",max1-min1);
}
}
}
return 0;
}