题目链接:http://codeforces.com/contest/961/problem/E
就是每次问一个区间有多少数大于k,直接离线树状数组就好了。
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=2e5+5; int a[MAXN]; struct query { int pos,k,val; query(int _pos=0,int _k=0,int _val=0):pos(_pos),k(_k),val(_val){} bool operator < (const query &o)const { return pos<o.pos; } }Q[MAXN*2]; struct BIT { int b[MAXN],n; void init(int _n) { n=_n; memset(b,0,sizeof(b)); } inline int lowbit(int x) { return x&(-x); } void update(int x,int val) { while(x<=n) { b[x]+=val; x+=lowbit(x); } } int query(int x) { int ret=0; while(x) { ret+=b[x]; x-=lowbit(x); } return ret; } }bit; int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n,tot=0; scanf("%d",&n); bit.init(n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]=min(a[i],n); if(a[i]<=i) continue; Q[++tot]=query(i,i-1,-1); Q[++tot]=query(a[i],i-1,1); } sort(Q+1,Q+1+tot); ll ans=0,p=1; for(int i=1;i<=n;i++) { bit.update(a[i],1); while(Q[p].pos<=i&&p<=tot) { int k=Q[p].k; int cnt=bit.query(n)-bit.query(k); ans+=Q[p].val*cnt; p++; } } printf("%lld\n",ans); return 0; }