POJ 3067

树状数组

求逆序数。我们先把所有的道路按照X升序,X相同时Y升序的方法排列。这样从头至尾便利,对于每条道路,我们只需要知道它之前有多少道路的Y大于它的Y就 可以了,所以我们只要知道前面有多少Y小于等于它的再用下标减去就可以了。

#include <cstdio>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
int c[1000010],k,m;
struct edge{
    int x,y;
}l[1000010];
int lowbit(int x){return x&(-x);}
ll sum(int b){
    ll sum=0;
    while(b>0){
        sum+=c[b];
        b-=lowbit(b);
    }
    return sum;
}
void add(int x){
    while(x<=m){
        ++c[x];
        x+=lowbit(x);
    }
}
bool cmp(edge a,edge b){
    return a.x==b.x?a.y<b.y:a.x<b.x;
}
int main(){
    int n,t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%d%d%d",&n,&m,&k);
        for(int j=1;j<=k;++j){
            scanf("%d%d",&l[j].x,&l[j].y);
        }
        memset(c,0,sizeof(c));
        sort(l+1,l+k+1,cmp);
        ll sum1=0;    //不用longlong会爆
        for(int j=1;j<=k;++j){
            sum1+=j-1-sum(l[j].y);       //因为下表从1开始,所以在减1
            add(l[j].y);
        }
        printf("Test case %d: %lld
",i,sum1);
    }
    return 0;
}
                
原文地址:https://www.cnblogs.com/Mr-Xu-JH/p/3896923.html