GFOJ64水一水

来源:互联网 发布:php base64解码成图片 编辑:程序博客网 时间:2024/06/10 06:41

http://www.gdfzoj.com/oj/problem/64
Problem Description
BNU ACM校队有n名队员,从1到n标号,每名队员根据自身情况拥有一个特征值,其中第i名队员的特征值是a[i]。现在BOSS问了m个问题,每个问题给定[l,r],要求小Q同学马上从标号位于区间[l,r]内的队员中选出两名队员,使得这两名队员的特征值相同,并且不默契度要尽可能小,两名队员的不默契度定义为两名队员标号之差的绝对值。对此小Q同学倍感压力,急需你的帮助。

Input
第一行包含2个整数n、m。

第二行包含n个整数a[1]、a[2]、…、a[n],保证0<=a[i]<2^31。

接下来m行,每行包含2个整数l、r,请注意所给的l、r均是经过加密的,解密方式是l=l xor lastans、r=r xor lastans,其中lastans表示上一次操作的输出结果,初始lastans=0,保证解密后1<=l<=r<=n。

对于30%的数据,1<=n,m<=5000。

对于60%的数据,1<=n,m<=50000。

对于100%的数据,1<=n,m<=500000。

Output
输出m行,每行包含一个整数,表示最小的两名队员的不默契度,如果不能选出满足条件的两名队员,请输出-1。

Sample Input
5 3

1 1 2 5 2

1 5

3 5

-4 -6

Sample Output
1

-1

2
dhr讲了分块的做法,but我自行脑补出RMQ的水法:
先预处理出下一个与a[i]相等的位置(双关键字,第一为左端点,排个序即可),然后用一个栈维护使右端点单调,因为若第i个区间右端点被前面的区间覆盖,显然此时应该用第i个区间取代前面的区间。这时左右端点均为单调,只要二分查找最左端>=l和最右端<=r的区间内最小值即可,用RMQ做即可。

#include <cstdio>#include <algorithm>#include <stack>#include <cstring>#include <cmath>#define INF 0x7f7f7f7f#define maxn 500000+50#define a_ first#define b_ secondusing namespace std;int p[maxn],q[maxn],ans,len,ll,rr,f[maxn][64],l,r,n,m,next[maxn],t;pair<int, int> a[maxn],b[maxn];stack< pair< int,int > > s;bool cmp(const pair < int,int > &a,const pair < int,int > &b ){    return a.b_<b.b_;}int main(){    //freopen("data.out","r",stdin);    //freopen("wa.out","w",stdout);    scanf("%d%d",&n,&m);    for (int i=1;i<=n;i++) scanf("%d",&a[i].a_),a[i].b_=i;    sort(a+1,a+n+1);    for (int i=1;i<=n;i++)       if (a[i].a_==a[i+1].a_)         //next[]=a[i+1].second();        b[++t]=make_pair(a[i].b_,a[i+1].b_);    //for (int i=1;i<=n;i++)    sort(b+1,b+1+t);    for (int i=1;i<=t;i++)      {        while (!s.empty()&&s.top().b_>b[i].b_)s.pop();        s.push(b[i]);      }    t=s.size();    memset(f,INF,sizeof(f));    for (int i=t;i>=1;i--) b[i]=s.top(),f[i][0]=b[i].b_-b[i].a_,s.pop();    for (int j=1;(1<<j)<=t;j++)      for (int i=1;i+(1<<j)-1<=t;i++)        f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);    //for (int i=t;i>=1;i--) a[i]=s.top(),s.pop();    for (int i=1;i<=t;i++) p[i]=b[i].a_,q[i]=b[i].b_;    for (int i=1;i<=m;i++)    {      scanf("%d%d",&l,&r);      l^=ans;r^=ans;      ll=lower_bound(p+1,p+1+t,l)-p;      rr=lower_bound(q+1,q+1+t,r+1)-q-1;      len=(int)((double)log(rr-ll+1)/(double)log(2.0));      if (ll>rr) ans=-1;      else ans=min(f[ll][len],f[rr-(1<<len)+1][len]);      printf("%d\n",ans);    }}
0 0
原创粉丝点击