题目链接:http://codeforces.com/problemset/problem/459/D
题意:给出一个数列,定义f(1, i, ai) 为区间[1,i]中所有大小等于ai的数的个数,求有多少对i,j满足f(1, i, ai) > f(j, n, aj)
思路:看了半天没看懂f(1, i, ai) 的定义……预处理好每一个f(1, i, ai) 与 f(j, n, aj),然后用f(1, i, ai)维护树状数组,然后再用f(j, n, aj)进行查询比它大的f(1, i, ai)有多少个就可以,思路就是求逆序数的思路,由于数据大小是10的9次方所以要离散化,(这道题用线段树求逆序也是可以的)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 1000030
using namespace std;
struct Node
{
int pos,val;
}s[maxn];
int c[maxn],sc[maxn],vis[maxn],pr[maxn],re[maxn];
bool cmp(Node p,Node q)
{
return p.val<q.val;
}
int lowbit(int x)
{
return x & (-x);
}
void add(int i)
{
while (i<maxn)
{
c[i]++;
i+=lowbit(i);
}
}
int sum(int i)
{
int s=0;
while (i>0)
{
s+=c[i];
i-=lowbit(i);
}
return s;
}
int main()
{
int n;
while (scanf("%d",&n)!=EOF)
{
for (int i=0;i<n;i++)
{
scanf("%d",&s[i].val);
s[i].pos=i;
}
sort(s,s+n,cmp);
int tem=1;
long long res=0;
sc[s[0].pos]=tem++;
for (int i=1;i<n;i++)
{
if (s[i].val!=s[i-1].val) sc[s[i].pos]=tem++;
else sc[s[i].pos]=sc[s[i-1].pos];
}
memset(vis,0,sizeof(vis));
for (int i=0;i<n;i++)
{
vis[sc[i]]++;
pr[i]=vis[sc[i]];
}
memset(vis,0,sizeof(vis));
for (int i=n-1;i>=0;i--)
{
vis[sc[i]]++;
re[i]=vis[sc[i]];
}
memset(c,0,sizeof(c));
for (int i=0;i<n;i++)
{
res+=i-sum(re[i]);
add(pr[i]);
}
printf("%I64d\n",res);
}
}