题意:
给定长度为n的序列a
问有多少个数对(x,y),满足:
x<y
a[x]>=y
a[y]>=x
数据范围:n<=2e5
解法:
三个条件:
x<y
a[x]>=y
a[y]>=x
其实前两个可以合并:
x<y<=a[x]
x<=a[y]
即对于每个x,计算[x,a[x]]范围内
满足x<=a[y]的y的数量
每次都暴力插入x<=a[y]的y然后查询显然不可取
观察到x<=a[y],满足左边x减少时x<=a[y]依然成立,因此可以不重置
另开一个结构体存{a[i],i},从大到小排序,枚举x,将满足x<=a[y]的y插入树状数组
每次答案累加[x,a[x]]就能计算出最后的答案
但是a[i]<=1e9,需要离散化,但是将a[x]离散化可能会影响x<=a[x]
其实当a[x]>n的时候,取a[x]=n就可以了
有个坑点是存在x>a[x],不满足x<y<a[x]中的x<a[x]
如果不特判直接用树状数组查询ask(a[x])-ask(x)会出现负数
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
struct BIT{
int c[maxm];
int lowbit(int i){return i&-i;}
void add(int i,int t){while(i<maxm)c[i]+=t,i+=lowbit(i);}
int ask(int i){int ans=0;while(i)ans+=c[i],i-=lowbit(i);return ans;}
}T;
struct Node{
int v,id;
bool operator<(Node a){
return v>a.v;
}
}e[maxm];
int a[maxm];
int n;
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]>n)a[i]=n;
e[i]={a[i],i};
}
sort(e+1,e+1+n);
int ans=0;
int k=1;
for(int i=n;i>=1;i--){//从大到小枚举x
while(k<=n&&e[k].v>=i){
T.add(e[k].id,1);
k++;
}
if(i<=a[i]){//坑点:i>a[i]的情况
ans+=T.ask(a[i])-T.ask(i);
}
}
cout<<ans<<endl;
return 0;
}