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
题意:
维护一个长为n的序列,支持两种操作:1.将[l,r]内的每个数增加x,2.对于给定的y,输出满足a[j]=a[i]=y的j-i的最大值,无解输出-1.
分析:
按sqrt(n)的大小分块,对于每一个块,维护块内元素的一个有序序列,对于操作1,如果整个块被修改操作覆盖,由于块内元素相对大小不变,只需打一个标记,如果某个块中有部分元素被修改,则暴力重构整个块,询问时对每个块分别查询,最后统计全局最优值。复杂度O(nlogn+qsqrt(n)logn)。
代码:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
ll a[500005];
vector<pair<ll,int> >s[805];
vector<int>res;
vector<pair<ll,int> >::iterator itr;
ll tag[805];
int main()
{
int n,q;
scanf("%d%d",&n,&q);
int b_s=(int)sqrt(n);
for(int i=0;i<n;i++)
{
scanf("%I64d",&a[i]);
}
int loc=-1;
for(int i=0;i<n;i++)
{
if(i%b_s==0)loc++;
s[loc].push_back(make_pair(a[i],i));
}
for(int i=0;i<=loc;i++)
{
sort(s[i].begin(),s[i].end());
}
int op,l,r;
ll x,y;
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%I64d",&l,&r,&x);
l--,r--;
int bl=l/b_s;
int br=r/b_s;
for(int i=bl+1;i<br;i++)
{
tag[i]+=x;
}
for(int i=0;i<s[bl].size();i++)
{
s[bl][i].first+=tag[bl];
if(s[bl][i].second>=l && s[bl][i].second<=r)
s[bl][i].first+=x;
}
sort(s[bl].begin(),s[bl].end());
tag[bl]=0;
if(br>bl)
{
for(int i=0;i<s[br].size();i++)
{
s[br][i].first+=tag[br];
if(s[br][i].second>=l && s[br][i].second<=r)
s[br][i].first+=x;
}
sort(s[br].begin(),s[br].end());
tag[br]=0;
}
}
else
{
scanf("%I64d",&y);
res.clear();
for(int i=0;i<=loc;i++)
{
itr=lower_bound(s[i].begin(),s[i].end(),make_pair(y-tag[i],0));
if(itr!=s[i].end() && (*itr).first==y-tag[i])res.push_back((*itr).second);
itr=lower_bound(s[i].begin(),s[i].end(),make_pair(y-tag[i]+1,0));
if(itr!=s[i].begin())
{
itr--;
if((*itr).first==y-tag[i])res.push_back((*itr).second);
}
}
if(res.empty())printf("-1\n");
else
{
sort(res.begin(),res.end());
printf("%d\n",res[res.size()-1]-res[0]);
}
}
}
return 0;
}