题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6534
Chika and Friendly Pairs
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 160 Accepted Submission(s): 52
Problem Description
Chika gives you an integer sequence a1,a2,…,an and m tasks. For each task, you need to answer the number of "friendly pairs" in a given interval.
friendly pair: for two integers ai and aj, if i<j and the absolute value of ai−aj is no more than a given constant integer K, then (i,j) is called a "friendly pair".A friendly pair (i,j) in a interval [L,R] should satisfy L≤i<j≤R.
Input
The first line contains 3 integers n (1≤n≤27000), m (1≤m≤27000) and K (1≤K≤109), representing the number of integers in the sequence a, the number of tasks and the given constant integer.
The second line contains n non-negative integers, representing the integers in the sequence a. Every integer of sequence a is no more than 109.
Then m lines follow, each of which contains two integers L, R (1≤L≤R≤n). The meaning is to ask the number of "friendly pairs" in the interval [L,R]。
Output
For each task, you need to print one line, including only one integer, representing the number of "friendly pairs" in the query interval.
Sample Input
7 5 3
2 5 7 5 1 5 6
6 6
1 3
4 6
2 4
3 4
Sample Output
0
2
1
3
1
Source
Recommend
liuyiding | We have carefully selected several similar problems for you: 6543 6542 6541 6540 6539
题意:找区间里a[i]-a[j]<=K的对数 i<j
思路:n和m都是27000 也就是2*10^4 1秒在10^7左右 所以我们还有10^3 普通莫队的复杂度是n^(3/2) 算一下27000当做25000的话 那么复杂度大概就是10^6 还有10可以用 显然用树结构来
维护求区间对数 树状数组复杂度log(n) 所以差不多就是10^7左右 果然是邀请赛的题,时间卡的是真的紧,,一点不让你浪费。 如果我们每次都用lower_bound和upperbound去找上下界
超时。。。 需要预处理上下界 这样就可以A这道题了
看代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9+7; const LL INF=1e9+7; const int maxn=27000+50; LL N,M,K; LL a[maxn],b[maxn]; LL c[maxn]; LL ans[maxn]; LL up[maxn],low[maxn]; LL block; LL len; struct query { LL l,r,num; }q[maxn]; bool cmp(const query x,const query y) { if(x.l/block==y.l/block) return x.r<y.r; return x.l<y.l; } int lowbit(int x) { return x&(-x); } int sea(LL x)//寻找大小为x的数在b数组中的下标 { int l=1,r=len; while(l<=r) { int mid=(l+r)>>1; if(b[mid]==x) return mid; else if(b[mid]>x) { r=mid-1; } else l=mid+1; } } void update(LL x,int add) { while(x<=27000) { c[x]+=add; x+=lowbit(x); } } LL Query(LL x) { LL ret=0; while(x>0) { ret+=c[x]; x-=lowbit(x); } return ret; } int main() { scanf("%lld%lld%lld",&N,&M,&K); block=sqrt(N); for(int i=1;i<=N;i++) { scanf("%lld",&a[i]); b[i]=a[i]; } // sort(a+1,a+1+N,cmp); sort(b+1,b+N+1); len=unique(b+1,b+N+1)-(b+1);//去重 for(int i=1;i<=M;i++) { scanf("%lld%lld",&q[i].l,&q[i].r); q[i].num=i; } sort(q+1,q+M+1,cmp); for(int i=1;i<=N;i++) { LL x=lower_bound(b+1,b+1+len,a[i]-K)-b; LL y=upper_bound(b+1,b+1+len,a[i]+K)-b-1; up[i]=y; low[i]=x-1; } LL L=1,R=0; LL ret=0; for(int i=1;i<=M;i++) { while(R<q[i].r)//区间增大 { // LL x=lower_bound(b+1,b+1+len,a[R+1]-K)-b; // LL y=upper_bound(b+1,b+1+len,a[R+1]+K)-b-1; //现在在b数组[x,y]之间的所有的数都是符合条件的 ret+=Query(up[R+1])-Query(low[R+1]); update(sea(a[R+1]),1);//这个必须放在上面的下面 因为如果先放的话本身的值岂不是算进去了 R++; } while(R>q[i].r)//区间减小 { update(sea(a[R]),-1);//这个必须放在下面的上面 因为你要减去它的影响 自然也不能算本身-本身 // LL x=lower_bound(b+1,b+1+len,a[R]-K)-b; // LL y=upper_bound(b+1,b+1+len,a[R]+K)-b-1; ret-=Query(up[R])-Query(low[R]); R--; } while(L<q[i].l)//区间减小 { update(sea(a[L]),-1); // solve(L,-1); // LL x=lower_bound(b+1,b+1+len,a[L]-K)-b; // LL y=upper_bound(b+1,b+1+len,a[L]+K)-b-1; ret-=Query(up[L])-Query(low[L]); L++; } while(L>q[i].l)//区间增大 { // LL x=lower_bound(b+1,b+1+len,a[L-1]-K)-b; // LL y=upper_bound(b+1,b+1+len,a[L-1]+K)-b-1; ret+=Query(up[L-1])-Query(low[L-1]); update(sea(a[L-1]),1); L--; } ans[q[i].num]=ret; } for(int i=1;i<=M;i++) printf("%lld\n",ans[i]); //cout<<ans[i]<<endl; return 0; }
原文地址:https://www.cnblogs.com/caijiaming/p/10896352.html