题目链接:
https://cn.vjudge.net/problem/HDU-6534
题目大意:
给你n,m,k。然后输入n个数,m个区间。然后问你每个区间满足|a[i]- a[j]|<=k的个数(i<=j)。
具体思路:
莫队处理每个区间,具体查询的时候通过树状数组查询。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 const int maxn = 2e6+100; 5 int n,m,k,block; 6 struct Point 7 { 8 int upp,low,val,now_pos; 9 } a[maxn]; 10 struct node 11 { 12 int st,ed,id; 13 node() {} 14 node(int xx,int yy,int zz) 15 { 16 st=xx,ed=yy,id=zz; 17 } 18 bool friend operator <(node t1,node t2) 19 { 20 if(t1.st/block!=t2.st/block) 21 return t1.st/block < t2.st/block; 22 return t1.ed/block<t2.ed/block; 23 } 24 } q[maxn]; 25 int ans[maxn]; 26 vector<int>sto; 27 int get_lower(int num) 28 { 29 return lower_bound(sto.begin(),sto.end(),num)-sto.begin()+1; 30 } 31 int get_upper(int num) 32 { 33 return upper_bound(sto.begin(),sto.end(),num)-sto.begin();// 注意这里是lower_bound 34 } 35 int tree[maxn]; 36 int sz; 37 int lowbit(int t) 38 { 39 return t&-t; 40 } 41 void add(int pos,int type) 42 { 43 while(pos<=sz) 44 { 45 tree[pos]+=type; 46 pos+=lowbit(pos); 47 } 48 } 49 int ask(int pos) 50 { 51 int num=0; 52 if(!pos) 53 return 0; 54 while(pos) 55 { 56 num+=tree[pos]; 57 pos-=lowbit(pos); 58 } 59 return num; 60 } 61 void solve() 62 { 63 int num=0; 64 int l=1,r=0; 65 for(int i=1; i<=m; i++) 66 { 67 while(l<q[i].st) 68 { 69 add(a[l].now_pos,-1); 70 num-=ask(a[l].upp)-ask(a[l].low-1); 71 l++; 72 } 73 while(l>q[i].st) 74 { 75 l--; 76 num+=ask(a[l].upp)-ask(a[l].low-1); 77 add(a[l].now_pos,1); 78 } 79 while(r<q[i].ed) 80 { 81 r++; 82 num+=ask(a[r].upp)-ask(a[r].low-1); 83 add(a[r].now_pos,1); 84 } 85 while(r>q[i].ed) 86 { 87 add(a[r].now_pos,-1); 88 num-=ask(a[r].upp)-ask(a[r].low-1); 89 r--; 90 } 91 ans[q[i].id]=num; 92 } 93 } 94 int main() 95 { 96 scanf("%d %d %d",&n,&m,&k); 97 for(int i=1; i<=n; i++) 98 { 99 scanf("%d",&a[i].val); 100 sto.push_back(a[i].val); 101 } 102 sort(sto.begin(),sto.end()); 103 sto.erase(unique(sto.begin(),sto.end()),sto.end());// 离散化 104 sz=sto.size(); 105 for(int i=1; i<=n; i++) 106 { 107 a[i].now_pos=get_lower(a[i].val);// 预处理出每个点的能到达的范围 108 a[i].low=get_lower(a[i].val-k); 109 a[i].upp=get_upper(a[i].val+k); 110 } 111 int st,ed; 112 for(int i=1; i<=m; i++) 113 { 114 scanf("%d %d",&st,&ed); 115 q[i]=node(st,ed,i); 116 } 117 block=(int)(sqrt(n)); 118 sort(q+1,q+m+1); 119 solve(); 120 for(int i=1; i<=m; i++) 121 { 122 printf("%d\n",ans[i]); 123 } 124 return 0; 125 }