您的位置:首页 > 其它

CF 459D - Pashmak and Parmida's problem (树状数组)

2014-08-16 15:34 447 查看
题意:给出n个数ai,定义f(l,r,x)为区间[l,r]中,与x相等的数的个数,求有多少对i,j,满足1<=i < j <=n,f(1,i,ai) > f(j,n,aj)。

思路:大胆暴力搞就好了。首先要预处理出来两个数组,一个是f[i],表示前i个数中,与a[i]相等的数的个数,一个是g[i],表示i~n中,与a[i]相等的数的个数。处理出来,从后向前扫,那么问题就变成了,对于当前扫到的i,有多少个g[j]小于f[i],对于这个,将g[i]按大小编号,每次插入到树状数组的对应位置就可以查询出来了。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn = 1000000+10;
int a[maxn],cntA[maxn],cntB[maxn],num[maxn];
map<int,int>mp;
int C[maxn];
inline int lowbit(int x)
{
    return x&-x;
}
int sum(int x)
{
    int ret=0;
    while(x>0)
    {
        ret+=C[x];
        x-=lowbit(x);
    }
    return ret;
}
void add(int x,int v)
{
    while(x<maxn)
    {
        C[x]+=v;
        x+=lowbit(x);
    }
}
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i = 1;i <= n;++i)
        scanf("%d",&a[i]);
    for(int i = 1;i <= n;++i)
    {
        if(mp.find(a[i]) == mp.end())
            cntA[i] = mp[a[i]] = 1;
        else cntA[i] = ++mp[a[i]];
    }
    mp.clear();
    for(int i = n;i >= 1;--i)
    {
        if(mp.find(a[i]) == mp.end())
            num[i-1] = cntB[i] = mp[a[i]] = 1;
        else num[i-1] = cntB[i] = ++mp[a[i]];
    }
    sort(num,num + n);
    int N = unique(num,num+n)- num;
    ll ans = 0;
    int pos;
    pos = pos = lower_bound(num,num+N,cntB
) - num;
    add(pos+1,1);
    for(int i = n-1;i >= 1;--i)
    {
        pos = lower_bound(num,num+N,cntA[i]) - num;
        if(pos > 0) ans +=sum(pos);
        pos = lower_bound(num,num+N,cntB[i]) - num;
        pos++;
        add(pos,1);
    }
    printf("%I64d\n",ans);
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐