POJ 3067 Japan(树状数组)

来源:互联网 发布:西南民族大学法学知乎 编辑:程序博客网 时间:2024/06/05 09:19

题目链接:
POJ 3067 Japan
题意:
左列有n个点,右列有m给点。点的编号都是从1开始,然后有k条线段a–b,表示连接左列的a和右列的b,
问这些线段的交点一共有多少?保证交点处有且仅有两条线段相交。
分析:
按照对m端点编号降序排列,m端点编号相同对n端点编号降序排列。
从0到k遍历这些线段,树状数组中保存n端点信息,对于线段i只需要查询树状数组中n端点<=a[i]的线段个数。
跟上一道树状数组类似。

//2940K 391MS#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAX_N=1010;int T,n,m,k,cases=0;long long bits[MAX_N];struct Way{    int a,b;    bool operator <(const Way tmp) const{//优先按照b降序排列,其次按照a降排列        if(b==tmp.b) return a>tmp.a;        else return b>tmp.b;    }}way[MAX_N*MAX_N];inline void update(int x){    for(int i=x;i<MAX_N;i+=(i&(-i))){        bits[i]++;    }}inline long long sum(int x){    long long res=0;    for(int i=x-1;i>0;i-=(i&(-i))){        res+=bits[i];    }    return res;}int main(){    //freopen("poj3067in.txt","r",stdin);    scanf("%d",&T);    while(T--){        scanf("%d%d%d",&n,&m,&k);        for(int i=0;i<k;i++){            scanf("%d%d",&way[i].a,&way[i].b);        }        sort(way,way+k);        memset(bits,0,sizeof(bits));        long long ans=0;        for(int i=0;i<k;i++){            ans+=sum(way[i].a);            update(way[i].a);        }        printf("Test case %d: %lld\n",++cases,ans);    }    return 0;}
0 0
原创粉丝点击