题目链接:https://nanti.jisuanke.com/t/41391
思路:nlogn找出所有合法(i,j),二维偏序查询
AC代码:
#include<bits/stdc++.h> #define lowbit(x) x&(-x) typedef long long ll; using namespace std; ll n,m; ll a[100005],pos[100005]; ll c[100005]; vector<ll> v[100005]; struct Query{ ll l,r; }q[100005]; struct Node{ ll x,y; bool operator<(const Node& b)const{ if(x==b.x) return y<b.y; return x<b.x; } }node[100005*4]; map<pair<ll,ll>,ll> sum; void add(ll x,ll val){ for(ll i=x;i<=n;i+=lowbit(i)){ c[i]+=val; } } ll getsum(ll x){ ll ret=0; for(ll i=x;i>0;i-=lowbit(i)){ ret+=c[i]; } return ret; } int main() { scanf("%lld%lld",&n,&m); for(ll i=1;i<=n;i++) scanf("%lld",&a[i]),pos[a[i]]=i; for(ll i=1;i<=n;i++){ for(ll j=a[i]*2;j<=n;j+=a[i]){ if(pos[j]>i) v[i].push_back(pos[j]); } } for(ll i=1;i<=n;i++){ for(ll j=a[i]*2;j<=n;j+=a[i]){ if(pos[j]<i) v[i].push_back(pos[j]); } } ll cnt=0; for(ll i=1;i<=m;i++) { scanf("%lld%lld",&q[i].l,&q[i].r); node[++cnt]=Node{q[i].r,q[i].r}; node[++cnt]=Node{q[i].l-1,q[i].l-1}; node[++cnt]=Node{q[i].l-1,q[i].r}; node[++cnt]=Node{q[i].r,q[i].l-1}; } sort(node+1,node+1+cnt); ll l=1; for(ll i=1;i<=cnt;i++){ while(l<=node[i].x){ for(auto j:v[l]) add(j,1); l++; } sum[make_pair(node[i].x,node[i].y)]=getsum(node[i].y); } for(ll i=1;i<=m;i++){ ll ans=sum[make_pair(q[i].r,q[i].r)]-sum[make_pair(q[i].l-1,q[i].r)]-sum[make_pair(q[i].r,q[i].l-1)]+sum[make_pair(q[i].l-1,q[i].l-1)]; printf("%lld ",ans); } return 0; }