简单分析一下,对于x<y,求a[x]>=y 同时a[y]>=x
再简化一下,求1-a[y]区间内大于>=y的个数。。。主席树牛逼
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const int maxx = 2e5+6;
struct node{
int l,r;
int cnt;
}tree[maxx*40];
int a[maxx];
int b[maxx];
int root[maxx];
int cnt;
vector<int>v;
int getval(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void inserts(int l,int r,int pre,int &now,int pos){
now=++cnt;
tree[now]=tree[pre];
tree[now].cnt++;
if(l==r){
return ;
}
int mid=(l+r)>>1;
if (pos<=mid){
inserts(l,mid,tree[pre].l,tree[now].l,pos);
}else {
inserts(mid+1,r,tree[pre].r,tree[now].r,pos);
}
}
int query(int L,int R,int l,int r,int w){
if(l==r){
return tree[R].cnt-tree[L].cnt;
}
int mid=(l+r)>>1;
if(w<=mid){
return tree[tree[R].r].cnt-tree[tree[L].r].cnt+query(tree[L].l,tree[R].l,l,mid,w);
}else {
return query(tree[L].r,tree[R].r,mid+1,r,w);
}
}
int main(){
int n;
while(~scanf("%d",&n)){
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
v.push_back(a[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n;i++){
b[i]=getval(a[i]);
}
for (int i=1;i<=n;i++){
inserts(1,n,root[i-1],root[i],b[i]);
}
LL ans=0;
for (int i=2;i<=n;i++){
ans+=query(root[0],root[min(a[i],i-1)],1,n,getval(i));
}
printf("%lld\n",ans);
}
return 0;
}