题意:很扯的题意,翻译过来就是给你一个长为n的数组,问你有多少对(i,j)满足i<j && a[i]>=j && a[j]>=i?
题解:我们考虑先满足后边的条件,即找到最大的x使得x<j && a[j]>=x,然后q[x-1].push_back(i),我们所存的是a[i]对于答案的贡献,其他类推,然后我们按原数组的顺序一个个的加入树状数组中并查询答案累加即可。注意答案会爆int
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 200005
#define ll long long
int c[maxn],a[maxn],n;
vector<int>q[maxn];
void update(int x,int val)
{
while(x<maxn)
c[x]+=val,x+=x&-x;
}
int query(int x)
{
int res=0;
while(x)
res+=c[x],x-=x&-x;
return res;
}
int main(void)
{
ll ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]=min(a[i],n);
q[min(i-1,a[i])].push_back(i);
}
for(int i=1;i<=n;i++)
{
update(a[i],1);
for(int j=0;j<q[i].size();j++)
ans+=query(n)-query(q[i][j]-1);
}
printf("%lld\n",ans);
return 0;
}