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
解法:因为涉及区间操作起先一开始想到的就是线段树,只是因为需要查找y的位置,线段树似乎并不能办到。于是接着转而想到了平方分桶,即是将整个区间分成sqrt(n)个桶,每个桶之中存储sqrt(n)个数。将桶内的元素排序,给每一个桶一个add值。表示整个桶的区间增加的数,如果对整个桶操作,直接对这个标记进行操作即可。如果是只有桶内一部分元素进行操作,直接遍历,因为桶内元素最多只有sqrt(n)个,所以大大降低了复杂度。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <cstdlib>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
#define rep(i,a,b) for (int i=a;i<((b)+1);i++)
#define Rep(i,a,b) for (int i=a;i>=b;i--)
#define foreach(e,x) for (__typeof(x.begin()) e=x.begin();e!=x.end();e++)
#define mid ((l+r)>>1) //segment tree
#define lson (k<<1) //segment tree
#define rson (k<<1|1) //segment tree
#define MEM(a,x) memset(a,x,sizeof a)
#define L ch[r][0] //splay tree
#define R ch[r][1] //splay tree
#define keyvalue ch[ch[root][1]][0] //splay tree
#define eps 1e-6
using namespace std;
const int N=600050;
const long long Mod=1e9+7;
const int inf=0x3f3f3f3f;
typedef pair<int, int> pii;
typedef long long ll;
typedef pair<ll,ll> pll;
typedef pair<ll,int> pli;
ll a[N],add[N];
vector<ll> vt[N];
int n,q,bk=1000,pos[N],bn=1;
bool cmp(const int &x,const int &y) {
return a[x]==a[y]?x<y:a[x]<a[y];
}
void update(int l,int r,ll x) {
int _l=pos[l],_r=pos[r];
if (_l==_r) {
rep(i,l,r) a[i]+=x;
sort(vt[_l].begin(),vt[_l].end(),cmp);
return ;
}
if (pos[l]==pos[l-1]) _l++;
if (pos[r]==pos[r+1]) _r--;
rep(i,_l,_r) add[i]+=x;
if (pos[l]==pos[l-1]) {
for (int i=l;pos[i]==_l-1;i++) a[i]+=x;
sort(vt[_l-1].begin(),vt[_l-1].end(),cmp);
}
if (pos[r]==pos[r+1]) {
for (int i=r;pos[i]==_r+1;i--) a[i]+=x;
sort(vt[_r+1].begin(),vt[_r+1].end(),cmp);
}
}
int query(ll x) {
int l=-1,r=-1;
rep(i,1,bn) {
a[0]=x-add[i];
vector<ll>::iterator it=lower_bound(vt[i].begin(),vt[i].end(),0,cmp);
if (it==vt[i].end()) continue;
if (a[*it]+add[i]==x) {
l=*it;
break;
}
}
if (l==-1) return -1;
Rep(i,bn,1) {
a[n+1]=x-add[i];
vector<ll>::iterator it=lower_bound(vt[i].begin(),vt[i].end(),n+1,cmp);
if (it==vt[i].begin()) continue;
it--;
if (a[*it]+add[i]==x) {
r=*it;
break;
}
}
return r-l;
}
int main() {
scanf("%d%d",&n,&q);
bn=(n/1000)+(n%1000>0);
rep(i,1,n) {
scanf("%lld",&a[i]);
pos[i]=(i-1)/1000+1;
vt[pos[i]].push_back(i);
}
rep(i,1,bn) sort(vt[i].begin(),vt[i].end(),cmp);
rep(i,1,q) {
int sw,l,r;
ll x;
scanf("%d",&sw);
if (sw==1) {
scanf("%d%d%lld",&l,&r,&x);
update(l,r,x);
}else {
scanf("%lld",&x);
printf("%d\n",query(x));
}
}
return 0;
}