给出一个含有n个元素的数列a和k值,询问m次,每次询问给出L,R,输出[L,R]中friendly pair的总个数。
friendly pair:对于数列位置i < j,有丨 a[i] - a[j] 丨<= k,则相当于一个friendly pair
第一行3个整数n(1 <= n <= 27000),m(1 <= n <= 27000), k(1 <= n <= 1e9)
第二行n个整数表示数列a,每个整数不超过1e9
接下来m行表示m个询问,每行两个整数L,R
7 5 3
2 5 7 5 1 5 6
6 6
1 3
4 6
2 4
3 4
0
2
1
3
1
当时只想到了莫队和树状数组,但是却没有离散化,而是用map数组储存,导致了时间复杂度为(n*√n*logn*logn),相对于正解多了个logn,导致无限TLE而铜牌,心塞了,就差一点点啊!
需要离散化,将数列的所有元素及其+k,-k离散化,这样使用树状数组时便不需要用到map而导致时间复杂度多了个logn。
莫队就不多说了,而树状数组的思路,类似于树状数组求逆序数。
下面是赛后写的代码,由于没有数据测试,不保证代码正确性,时间复杂度(n*√n*logn)
#include
#define ll long long
using namespace std;
const int maxn = 27010;
struct node{
int l,r,id;
}que[maxn];
int a[maxn];
int b[maxn*3];
int ans[maxn];
int sum[maxn*3];
int size,limit,n,m,k;
map mp;
void add(int p, int x){ //给位置p增加x
while(p <= size) sum[p] += x, p += p & -p;
}
int ask(int p){ //求位置p的前缀和
int res = 0;
while(p) res += sum[p], p -= p & -p;
return res;
}
int range_ask(int l, int r){ //区间求和
return ask(r) - ask(l - 1);
}
bool cmp(node x,node y){
if(x.l/limit == y.l/limit)
return x.r < y.r;
return x.l/limit < y.l/limit;
}
void solve()
{
int L,R,ans1;
L = R = 1;
ans1 = 0;
add(mp[a[1]],1);
for(int i = 1;i <= m;i++)
{
while(que[i].l > L)
{
add(mp[a[L]],-1);
ans1-=range_ask(mp[a[L]-k],mp[a[L]+k]);
L++;
}
//减
while(que[i].r < R)
{
add(mp[a[R]],-1);
ans1-=range_ask(mp[a[R]-k],mp[a[R]+k]);
R--;
}
//减
while(que[i].l < L)
{
L--;
ans1+=range_ask(mp[a[L]-k],mp[a[L]+k]);
add(mp[a[L]],1);
}
//加
while(que[i].r > R)
{
R++;
ans1+=range_ask(mp[a[R]-k],mp[a[R]+k]);
add(mp[a[R]],1);
}
//加
ans[que[i].id] = ans1;
}
for(int i = 1;i <= m;i++)
printf("%d\n",ans[i]);
}
int main(){
while(~scanf("%d%d%d",&n,&m,&k)){
memset(sum,0,sizeof(sum));
limit = (int)(sqrt(n)+0.5);
mp.clear();
for(int i = 1,j = 1;i <= n;i++){
scanf("%d",&a[i]);
b[j++] = a[i];
b[j++] = a[i]+k;
b[j++] = a[i]-k;
}
for(int i = 1;i <= m;i++){
scanf("%d%d",&que[i].l,&que[i].r);
que[i].id = i;
}
sort(b+1,b+1+3*n);
sort(que+1,que+1+m,cmp);
size = unique(b+1,b+1+3*n)-b-1;
for(int i = 1;i <= size;i++){
mp[b[i]] = i;
}
solve();
}
return 0;
}
/*
7 5 3
2 5 7 5 1 5 6
6 6
1 3
4 6
2 4
3 4
*/