tjut 3015

#include<iostream>
#include<algorithm>
using namespace std;
#define M 100005
struct node
{
    __int64 a,b;
    int num1,num2;
}t[M];
int cmpa(node &p,node &q)
{
    if(p.a<q.a)
        return 1;
    else
        return 0;
}
int cmpb(node &p,node &q)
{
    if(p.b<q.b)
        return 1;
    else
        return 0;
}
int cmpn(node &p,node &q)
{
    if(p.num2<q.num2)
        return 1;
    else
        return 0;
}
__int64 c[M],d[M],n;                    //c用来处理一个数前面或者后面比它大或者小的数之和,d用来处理这个数前面或者后面有多少个数
int lowbit(int x)                      //比它大或者小
{
    return x&(-x);
}
void updatac(int i,int j)
{
    while(i<=n)
    {
        c[i]+=j;
        i+=lowbit(i);
    }
}
void updatad(int i,int j)
{
    while(i<=n)
    {
        d[i]+=j;
        i+=lowbit(i);
    }
}
__int64 getsumc(int x)
{
    __int64 s=0;
    while(x>0)
    {
        s+=c[x];
        x-=lowbit(x);
    }
    return s;
}
__int64 getsumd(int x)
{
    __int64 s=0;
    while(x>0)
    {
        s+=d[x];
        x-=lowbit(x);
    }
    return s;
}
int main()
{
    while(scanf("%d",&n)>0)
    {
        memset(c,0,sizeof(c));
        memset(d,0,sizeof(d));
        int i;
        for(i=1;i<=n;i++)
        {
            scanf("%I64d%I64d",&t[i].a,&t[i].b);
        }
        sort(t+1,t+1+n,cmpa);
        for(i=1;i<=n;i++)
        {
            if(i!=1&&t[i].a==t[i-1].a)
                t[i].num1=t[i-1].num1;
            else
                t[i].num1=i;
        }
        int max=t[n].num1;
        //printf("%d\n",max);
        sort(t+1,t+1+n,cmpb);
        for(i=1;i<=n;i++)
        {
            if(i!=1&&t[i].b==t[i-1].b)
                t[i].num2=t[i-1].num2;
            else
                t[i].num2=i;
        }
        sort(t+1,t+1+n,cmpn);                //这之前都是对等级进行处理
        for(i=1;i<=n;i++)               //插入数据
        {
            updatac(t[i].num1,t[i].num1);
            updatad(t[i].num1,1);
            //printf("%d %d\n",t[i].num1,t[i].num2);
        }
        //printf("\n\n\n");
        __int64 sum=0,m=n,tmp1,tmp2;
        for(i=1;i<n;i++)
        {  
            //printf("%I64d\t %I64d\t %I64d\t %I64d\n",getsumc(max),getsumc(t[i].num1),n-getsumd(t[i].num1),t[i].num2);
            //sum+=(getsumc(max)-getsumc(t[i].num1)-(m-getsumd(t[i].num1))*t[i].num1)*t[i].num2;
            /*
            在这里,sum错了一次,一开始是想,算出所有数之和-小于等于t[i].num1的数之和,再减去t[i].num1这个数与其他数相减的次数*t[i].num1;
            这样做是错的,这组数据过不了:
            4 1
            1 2
            4 3
            1 4
            3 4
            正确结果是37.
            */
            //printf("%I64d\t%I64d\n",getsumc(max),getsumc(100));
            tmp1=getsumd(t[i].num1-1)*t[i].num1-getsumc(t[i].num1-1);
            tmp2=(getsumd(max)-getsumd(t[i].num1))*t[i].num1-(getsumc(max)-getsumc(t[i].num1));
            /*
            之后,我再思考,发现可以先求出t[i].num后面比t[i].num小、大的数之和,还有比它小、大的数的个数,用比它小的数的个数*它本身-比
            它小的数之和,再求出比它大的数的个数*它本身-比它大的数.............;再这两个数相减....结果就出来了;但是,每求出一个数后,
            要把这个数删除,以免下面会重复求这个数.............
            */
            sum+=(tmp1-tmp2)*t[i].num2;
            updatac(t[i].num1,-t[i].num1);
            updatad(t[i].num1,-1);
            m--;
        }
        printf("%I64d\n",sum);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值