Professor GukiZ was playing with arrays again and accidentally discovered new function, which he called GukiZiana. For given array a, indexed with integers from 1 to n, and number y, GukiZiana(a, y) represents maximum value of j - i, such that aj = ai = y. If there is no y as an element in a, then GukiZiana(a, y) is equal to - 1. GukiZ also prepared a problem for you. This time, you have two types of queries:
- First type has form 1 l r x and asks you to increase values of all ai such that l ≤ i ≤ r by the non-negative integer x.
- Second type has form 2 y and asks you to find value of GukiZiana(a, y).
For each query of type 2, print the answer and make GukiZ happy!
The first line contains two integers n, q (1 ≤ n ≤ 5 * 105, 1 ≤ q ≤ 5 * 104), size of array a, and the number of queries.
The second line contains n integers a1, a2, ... an (1 ≤ ai ≤ 109), forming an array a.
Each of next q lines contain either four or two numbers, as described in statement:
If line starts with 1, then the query looks like 1 l r x (1 ≤ l ≤ r ≤ n, 0 ≤ x ≤ 109), first type query.
If line starts with 2, then th query looks like 2 y (1 ≤ y ≤ 109), second type query.
For each query of type 2, print the value of GukiZiana(a, y), for y value for that query.
4 3
1 2 3 4
1 1 2 1
1 1 1 1
2 3
2
2 3
1 2
1 2 2 1
2 3
2 4
0
-1
【分析】给出一个数组a,然后q次操作,1 l r x表示将区间[l,r]所有数+1 ; 2 y表示询问这个数组中最左边的y和最右边的y的下标差为多少。
可分块做。将所有块里面的数排序,(便于查找要查询的y)。对于更新操作,单独处理左端点和右端点的块,改变a[i];然后对于中间跨过的块,用lazy数组标记add值。
对于查询操作,依次遍历每个块,二分查找y的位置即可。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <queue> #include <vector> #define inf 1000000000 #define met(a,b) memset(a,b,sizeof a) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 typedef long long ll; using namespace std; const int N = 5e5+5; const int M = 7e2+50; int n,m; int l[N],r[N],belong[N]; int cnt,num,x,v,ans; int a[N],tot[M],lazy[M]; pair<int,int>p[M][M]; void init(){ num=sqrt(n); cnt=n/num; if(n%num)cnt++; for(int i=1;i<=n;i++){ belong[i]=(i-1)/num+1; } for(int i=1;i<=cnt;i++){ l[i]=(i-1)*num+1; r[i]=min(n,i*num); for(int j=l[i];j<=r[i];j++){ p[i][++tot[i]]=make_pair(a[j],j); } sort(p[i]+1,p[i]+1+tot[i]); } } void update1(int b,int x){ if(lazy[b]+x>inf)lazy[b]=inf+1; else lazy[b]+=x; } void update2(int b,int ll,int rr,int x){ if(ll==l[b]&&rr==r[b]){ update1(b,x); return; } for(int i=1;i<=tot[b];i++){ int po=p[b][i].second; if(po>=ll&&po<=rr){ p[b][i].first+=x; if(p[b][i].first>inf)p[b][i].first=inf+1; } } sort(p[b]+1,p[b]+tot[b]+1); } int main() { int op,ll,rr,x,y; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); init(); while(m--){ scanf("%d",&op); if(op==1){ scanf("%d%d%d",&ll,&rr,&x); if(belong[ll]==belong[rr])update2(belong[ll],ll,rr,x); else { for(int i=belong[ll]+1;i<=belong[rr]-1;i++)update1(i,x); update2(belong[ll],ll,r[belong[ll]],x); update2(belong[rr],l[belong[rr]],rr,x); } } else { scanf("%d",&y); int last=0,fir=0; for(int i=cnt;i>=1;i--){ if(!last){ int po=upper_bound(p[i]+1,p[i]+tot[i]+1,make_pair(y-lazy[i],1000000))-p[i]-1; if(p[i][po].first+lazy[i]==y){ fir=last=p[i][po].second; } } int po=lower_bound(p[i]+1,p[i]+tot[i]+1,make_pair(y-lazy[i],0))-p[i]; if(p[i][po].first+lazy[i]==y){ fir=p[i][po].second; } } if(!last)puts("-1"); else printf("%d ",last-fir); } } return 0; }