简单分析一下,对于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 ",ans); } return 0; }