题目链接: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;
}