質問:
2つのベクトル間の距離は∑ ∣ a [i] − b [i] ∣ p ∑ | a [i] -b [i] | ^ p∑∣ a [ i ]−b [ i ] ∣p。
2つの配列がある場合、2つの配列のそれぞれが(同じ長さの)ベクトルとしてサブ配列を取得し、距離がvを超えないように、サブベクトルのペアの数を見つけます。
アイデア:
2つのサブアレイの開始点の違いを列挙してから、ダブルポインターを維持します。
一度[l1、r 1] −> [l 2、r 2] [l1、r1]-> [l2、r2][ l 1 、R 1 ] ->>[ L 2 、r 2 ]この間隔が満たされると、[l 11、r 1] −> [l 22、r 2]は、l 1 <l11≤r1、l 2 <l22≤r2[l11、r1]-を満たします。 > [l22、r2]、l1 <l11≤r1、l2 <l22≤r2を満たす[ l 1 1 、R 1 ] ->>[ L 2 2 、R&LT 2 ] 、フルフットL 1<l 1 1≤r 1 、l 2<l 2 2≤r 2、ここには単調性があります。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn = 4e5 + 7;
ll a[maxn],b[maxn];
ll qpow(ll x,ll n) {
ll res = 1;
for(int i = 1;i <= n;i++) {
res *= x;
}
return res;
}
int main() {
int T;scanf("%d",&T);
while(T--) {
ll n,v,p;scanf("%lld%lld%lld",&n,&v,&p);
for(int i = 1;i <= n;i++) {
scanf("%lld",&a[i]);
}
for(int i = 1;i <= n;i++) {
scanf("%lld",&b[i]);
}
ll ans = 0;
for(int len = 0;len <= n - 1;len++) {
//两个指针的差距
int l1 = 1,r1 = 1; //第一个人的指针
int l2 = 1 + len,r2 = 1 + len; //第二个人的指针
ll tmp = qpow(abs(a[l1] - b[l2]),p);
while(r2 <= n) {
if(tmp <= v) {
ans += r1 - l1 + 1;
r2++;
r1++;
tmp += qpow(abs(a[r1] - b[r2]),p);
} else {
tmp -= qpow(abs(a[l1] - b[l2]),p);
l1++;
l2++;
if(l1 > r1) {
r1++;
r2++;
tmp += qpow(abs(a[r1] - b[r2]),p);
}
}
}
if(len == 0) continue;
l1 = 1 + len,r1 = 1 + len;
l2 = 1,r2 = 1;
tmp = qpow(abs(a[l1] - b[l2]),p);
while(r1 <= n) {
if(tmp <= v) {
ans += r1 - l1 + 1;
r2++;
r1++;
tmp += qpow(abs(a[r1] - b[r2]),p);
} else {
tmp -= qpow(abs(a[l1] - b[l2]),p);
l1++;
l2++;
if(l1 > r1) {
r1++;
r2++;
tmp += qpow(abs(a[r1] - b[r2]),p);
}
}
}
}
printf("%lld\n",ans);
}
return 0;
}