给定两个全排列 |A|=n <= |B|=m
问有多少种不同的d使得数组A里面的所有值全部+d之后
是数组B的子序列
然后就是枚举+0,+1,+2,+3…
hash判断一下
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=200010;
const int B=10007;
int N,M,pos[maxn];
LL xp[maxn];
LL val,sum;
struct IntervalTree{
LL hash[maxn<<2];
int cnt[maxn<<2];
void build(int o,int l,int r){
hash[o]=cnt[o]=0;
if(l==r)return ;
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
}
void pushup(int o){
hash[o]=hash[o<<1]*xp[cnt[o<<1|1]]+hash[o<<1|1];
cnt[o]=cnt[o<<1]+cnt[o<<1|1];
}
void update(int o,int l,int r,int pos,int val,int num){
if(l==r){
hash[o]+=num*val;
cnt[o]+=num;
return;
}
int mid=(l+r)>>1;
if(pos<=mid)update(o<<1,l,mid,pos,val,num);
else update(o<<1|1,mid+1,r,pos,val,num);
pushup(o);
}
}tree;
int main(){
while(scanf("%d%d",&N,&M)!=EOF){
val=sum=0;
xp[0]=1;
for(int i=1;i<=N;i++){xp[i]=xp[i-1]*B;sum+=xp[i-1];}
for(int i=1;i<=N;i++){
int x;
scanf("%d",&x);
val=val*B+x;
}
for(int i=1;i<=M;i++){
int x;
scanf("%d",&x);
pos[x]=i;
}
tree.build(1,1,M);
int ans=0;
for(int i=1;i<=M;i++){//����ֵ1~M��˳������߶�����
tree.update(1,1,M,pos[i],i,1);
if(i>=N)
{
if(tree.hash[1]-(sum*(i-N))==val)
ans++;
tree.update(1,1,M,pos[i-N+1],i-N+1,-1);
}
}
printf("%d\n",ans);
}
return 0;
}