codeforces_459D_(线段树,离散化,求逆序数)

链接:http://codeforces.com/problemset/problem/459/D

D. Pashmak and Parmida's problem
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she wants her partner to be clever too (although he's not)! Parmida has prepared the following test problem for Pashmak.

There is a sequence a that consists of n integers a1, a2, ..., an. Let's denote f(l, r, x) the number of indices k such that: l ≤ k ≤ r andak = x. His task is to calculate the number of pairs of indicies i, j (1 ≤ i < j ≤ n) such that f(1, i, ai) > f(j, n, aj).

Help Pashmak with the test.

Input

The first line of the input contains an integer n (1 ≤ n ≤ 106). The second line contains n space-separated integers a1, a2, ..., an(1 ≤ ai ≤ 109).

Output

Print a single integer — the answer to the problem.

Examples
input
7
1 2 1 1 2 2 1
output
8
input
3
1 1 1
output
1
input
5
1 2 3 4 5
output
0

题意:f(1,i,ai)表示(1,i)中等于ai的个数,f(j,n,aj)表示(j,n)中与aj相等的个数,求有多少对(i,j)。(特么,之前题意看错了,想了一上午没想明白,结果。。。)
思路:可以用数组fro统计每个位置(包括该位置)其前面有多少个与它相等的数,用beh数组统计每个位置其后有多少个与它相等的数。
  样例:
    7
    1 2 1 1 2 2 1
    fro:{1,1,2,3,2,3,4}  
    beh:{4,3,3,2,2,1,1}

问题就转化为求第一个序列相对第二个序列的逆序数(因为相当于i可以从fro中查看,j可以从beh中查看)
线段树求逆序数。。。
可以从前往后处理,也可以从后往前处理。
貌似从后往前更好理解。
从后往前处理,即,将beh依次插入树中,每插一个,查询其对应的fro的元素(1,fro[i]-1)区间也就是小于fro[i]的个数(查当前树中比fro[i]小的个数)
从前往后跟以上思路相反,插fro查beh(差当前树中比beh[i]大的个数)。
代码中第一次接触到离散化,以后可以借鉴。
此题还需多加理解。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
struct Node
{
    int l,r;
    int num;
} tree[1000000<<2];

int num[1000005];
int fro[1000005],beh[1000005],sum[1000005];
map<int,int> m1;

void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].num=0;
    if(tree[rt].l==tree[rt].r)
        return;
    int mid=(l+r)/2;
    build(lson);
    build(rson);
}

void update(int x,int l,int r,int rt)
{
    tree[rt].num++;
    if(tree[rt].l==tree[rt].r&&tree[rt].l==x)
        return;
    int mid=(l+r)/2;
    if(x<=mid)
        update(x,lson);
    else
        update(x,rson);
}

int query(int L,int R,int l,int r,int rt)
{
    if(L>R)
        return 0;
    if(L==l&&R==r)
        return tree[rt].num;
    int mid=(l+r)/2;
    if(R<mid)
        return query(L,R,lson);
    else if(L>mid)
        return query(L,R,rson);
    else
        return query(L,mid,lson)+query(mid+1,R,rson);

}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&num[i]);
    int cnt=1;
    for(int i=1; i<=n; i++)  ///离散化,以后可以借鉴
    {
        if(!m1[num[i]])
            m1[num[i]]=cnt++;
        num[i]=m1[num[i]];
    }
    cnt=0;
    memset(sum,0,sizeof(sum));
    for(int i=1; i<=n; i++)
    {
        sum[num[i]]++;
        fro[i]=sum[num[i]];
        cnt=max(cnt,fro[i]);
    }
    memset(sum,0,sizeof(sum));
    for(int i=n; i>=1; i--)
    {
        sum[num[i]]++;
        beh[i]=sum[num[i]];
    }
    build(1,cnt,1);
    long long ans=0;
    for(int i=n; i>1; i--)
    {
        update(beh[i],1,cnt,1);
        //cout<<"**"<<endl;
        ans+=query(1,fro[i-1]-1,1,cnt,1);
        //cout<<ans<<'*'<<endl;
    }
    printf("%I64d\n",ans);
    return 0;
}

 

posted on 2016-05-09 20:31  JASONlee3  阅读(318)  评论(0编辑  收藏  举报

导航