思路:
求满足a[x]>=y&&a[y]>=x&&x<y的对数。
用c[i]记录大于等于(等于i的元素的下标)的个数。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
using namespace std;
#define MAXN 200005
int n,t[MAXN],c[MAXN];
int p[MAXN];
vector<int> vec[MAXN];
int lowbit(int i)
{
return i&(-i);
}
void add(int i,int x)
{
while(i<=n)
{
c[i]+=x;
i+=lowbit(i);
}
}
int sum(int i)
{
int res=0;
while(i)
{
res+=c[i];
i-=lowbit(i);
}
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
vec[i].clear();
for(int i=1; i<=n; i++)
{
scanf("%d",&p[i]);
if(p[i]>n) vec[n].push_back(i);
else vec[p[i]].push_back(i);//存储等于p[i]的元素下标
}
long long ans=0;
memset(c,0,sizeof c);
for(int i=n; i>=1; i--)//从大到小枚举i
{
for(int j=0; j<vec[i].size(); j++)//将等于i的元素添加进去
add(vec[i][j],1);
ans+=sum(min(i-1,p[i]));//查询下标小于i(在i之前),且小于等于p[i](与第i个点可以互相到达)的个数
}
printf("%lld\n",ans);
return 0;
}