码迷,mamicode.com
首页 > 编程语言 > 详细

Contest (树状数组求逆序对)

时间:2020-06-04 13:32:15      阅读:60      评论:0      收藏:0      [点我收藏+]

标签:end   using   com   long   ring   get   逆序   tps   include   

 

题目链接:https://ac.nowcoder.com/acm/problem/13947

题目大意:有n个队伍参加三场比赛,如果队伍x有一场比赛赢了队伍y,y也有一场比赛赢了x,就算一组,求有多少组。

思路:这里我用了树状数组求逆序对的方法,先对第一场比赛进行排序,然后求第二场和第三场的逆序对,之后再对第二场比赛进行排序,求第三场比赛的逆序对,最后再除个2即可。详细的过程写到注释里了。

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <cmath>
#define ll long long
#define pi 3.1415927
#define inf 0x3f3f3f3f
#define mod 1000000007
using namespace std;
int n,a[200005],c[200005];
struct node{
    int x,y,z;
}tr[200005];
bool rankx (node x ,node y) ///对第一场比赛排序
{
    return x.x<y.x;
}
bool ranky (node x,node y) ///对第二场比赛排序
{
    return x.y<y.y;
}

int lowbit(int i)
{
    return i&-i;
}
void add(int i, int k) 
{
    while(i<=n)
    {
        c[i]+=k;
        i+=lowbit(i);
    }
}
int getsum(int i)
{
    int sum=0;
    while(i>0)
    {
        sum+=c[i];
        i-=lowbit(i);
    }
    return sum;
}

int main ()
{
    int m,i,t,j,k,p=1;
    ll sum=0;
    cin>>n;
    for(i=1;i<=n;++i)
        scanf("%d %d %d",&tr[i].x,&tr[i].y,&tr[i].z);
    ///第一次先对第一场比赛排序
    sort(tr+1,tr+n+1,rankx);
    for(i=1;i<=n;++i){
        add(tr[i].y,1);
        sum+=i-getsum(tr[i].y);  ///求第二场的逆序对
    }
    memset(c,0,sizeof(c)); ///重置一下
    for(i=1;i<=n;++i){
        add(tr[i].z,1);
        sum+=i-getsum(tr[i].z);///再求第三场的逆序对
    }
    ///按照第二场比赛排序,然后求第三场的逆序对
    sort(tr+1,tr+n+1,ranky);
    memset(c,0,sizeof(c));
    for(i=1;i<=n;++i){
        add(tr[i].z,1);
        sum+=i-getsum(tr[i].z); 
    }

    cout<<sum/2<<endl;

    return 0;
}

 

Contest (树状数组求逆序对)

标签:end   using   com   long   ring   get   逆序   tps   include   

原文地址:https://www.cnblogs.com/blowhail/p/13042638.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!