GTY’s gay friends
题意
给出n个数字,以及m个询问,每个询问给出一个区间[l,r],判断这个区间是不是[1,r-l+1]的全排列。
思路1
首先我们可以通过前缀和进行第一次判断。
这时区间中可能会有重复的元素。
维护一个数组tmp[i]表示第i个元素前一次出现的位置,我们只需要保证[l,r]所有的tmp[i]都小于l就可以了。
这一步使用线段树维护tmp[i]最大值。
代码
//#include<bits/stdc++.h>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<stack>
#include<map>
#include<string>
#include<iostream>
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-10;
int n,m;
int pos[N],val[N*4],tmp[N];
ll pre[N];
void build(int rt,int l,int r)
{
if(l==r)
{
val[rt]=tmp[l];
return ;
}
int mid=(l+r)>>1;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
val[rt]=max(val[rt<<1],val[rt<<1|1]);
}
int query(int rt,int l,int r,int qs,int qe)
{
if(qs<=l&&qe>=r)
return val[rt];
int mid=(l+r)>>1;
int ans=0;
if(qs<=mid)
ans=query(rt<<1,l,mid,qs,qe);
if(qe>mid)
ans=max(ans,query(rt<<1|1,mid+1,r,qs,qe));
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(pos,0,sizeof(pos));
for(int i=1; i<=n; ++i)
{
int x;
scanf("%d",&x);
pre[i]=pre[i-1]+x;
tmp[i]=pos[x];
pos[x]=i;
}
build(1,1,n);
for(int i=1; i<=m; ++i)
{
int l,r;
scanf("%d%d",&l,&r);
ll len=r-l+1;
if((pre[r]-pre[l-1]==len*(len+1)/2)&&query(1,1,n,l,r)<l)
printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
/*
8 5
2 1 3 4 5 2 3 1
1 3
1 1
2 2
4 8
1 5
3 2
1 1 1
1 1
1 2
*/
思路2
给1-n随机一个权值,维护1-i的异或和。
对于给定的序列,也维护一个异或和。
判断的时候判断对应的异或和是否相等即可。
复杂度为O(n)
代码
//#include<bits/stdc++.h>
#include<math.h>
#include<time.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<stack>
#include<map>
#include<string>
#include<iostream>
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-10;
int n,m;
ull hash1[N],arr[N],ra[N],sum[N];
int main()
{
srand(time(NULL));
for(int i=1;i<=1000000;++i)
{
ra[i]=rand()*rand();//0~32767
hash1[i]=hash1[i-1]^ra[i];
}
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;++i)
{
int x;
scanf("%d",&x);
sum[i]=sum[i-1]+x;
arr[i]=arr[i-1]^ra[x];
}
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
ll len=(r-l+1);
if((sum[r]-sum[l-1]==(len+1)*(len)/2)&&(hash1[len]==(arr[r]^arr[l-1])))
printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
/*
*/