题目大意: 给你一个长度为n的序列,有m次查询操作,每次查询[L,R]区间的友好对的个数。
友好对的定义:满足i<j,且|ai-aj|<=K。
题解:首先我们把题意转换一下,相当于枚举[L,R]区间内每个值a[i],且[L,R]区间内值在[ai-k,ai+k]的数的个数。
这时候我们发现这是树状数组一个很经典的用法:求所有值在一段区间的的数的个数(类似于求逆序数的做法)。
但是我们发现值比较大,而树状数组不可能开这么大的空间,但是可以发现数的范围比较小,因此可以考虑离散化。
最后我们把所有查询离线处理一下,其实也是很经典的莫队做法,考虑一下L,R左移右移时对答案的贡献就行了。
时间复杂度:O(n*sqrt(n)*log(n))
代码实现:
#pragma GCC optimize(2) #include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <cstdio> #include <cstdlib> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #define PI atan(1.0) * 4 #define E 2.718281828 #define rp(i, s, t) for (register int i = (s); i <= (t); i++) #define RP(i, t, s) for (register int i = (t); i >= (s); i--) #define ll long long #define ull unsigned long long #define mst(a, b) memset(a, b, sizeof(a)) #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define pii pair<int, int> #define mp make_pair #define pb push_back #define debug printf("ac\n"); using namespace std; inline int read() { int a = 0, b = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') b = -1; c = getchar(); } while (c >= '0' && c <= '9') { a = (a << 3) + (a << 1) + c - '0'; c = getchar(); } return a * b; } const int INF = 0x3f3f3f3f; const int N = 27000+7; int B[N*3]; int n,m,k; int a[N]; int L=1,R=0,res[N],ans; int block,num,belong[N]; struct query{ int l,r,id; }q[N]; bool cmp(const query& a,const query& b){ return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:((belong[a.l]&1)?a.r<b.r:a.r>b.r); } inline lowbit(int x){return x&(-x);} inline int query(int index){ int res=0; for(int i=index;i>=1;i-=lowbit(i)) res+=B[i]; return res; } inline void update(int index,int val){ for(int i=index;i<=N*3-7;i+=lowbit(i)) B[i]+=val; } vector<int> v; int up[N],down[N],cur[N]; inline void add(int pos){ ans+=query(up[pos])-query(down[pos]-1); update(cur[pos],1); } inline void del(int pos){ update(cur[pos],-1); ans-=query(up[pos])-query(down[pos]-1); } int main() { n=read(),m=read(),k=read(); rp(i,1,n) a[i]=read(),v.pb(a[i]),v.pb(a[i]-k),v.pb(a[i]+k); sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); block=sqrt(n); num=n/block;if(n%block) num++; rp(i,1,n) belong[i]=(i-1)/block+1; rp(i,1,m) q[i].l=read(),q[i].r=read(),q[i].id=i; sort(q+1,q+1+m,cmp); rp(i,1,n){ up[i]=lower_bound(v.begin(),v.end(),a[i]+k)-v.begin()+1; down[i]=lower_bound(v.begin(),v.end(),a[i]-k)-v.begin()+1; cur[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1; } rp(i,1,m){ int ql=q[i].l,qr=q[i].r; while(L<ql) del(L++); while(ql<L) add(--L); while(R<qr) add(++R); while(qr<R) del(R--); res[q[i].id]=ans; } rp(i,1,m) printf("%d\n",res[i]); return 0; }
2019湘潭邀请赛C - Chika and Friendly Pairs——莫队+树状数组+离散化
猜你喜欢
转载自blog.csdn.net/qq_43472263/article/details/104911109
今日推荐
周排行