void-man

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

给出N,M,K从N向M连K条边,问有多少个交点?

可以把左边的序列进行从大到小排序,然后求右边的序列中,大于当前值的有多少组,把每组数的满足此条件的个数加起来就是题目要求

直接往后递归可以得出答案O(n^2),但是超时,所以可以用树状数组,每次可以把当前数向上更新,把每个数小于自己的数的个数进行更新

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAX  1010
using namespace std;
long long c[MAX];
long long sum;
int N,M,K;
struct st
{
    int x,y;
}sts[MAX*MAX];
bool cmp(st a,st b)
{
    if(a.x==b.x)return a.y>b.y;
    return a.x>b.x;
}
int lowbit(int x)
{
    return x &(-x);
    
}
void update(int x)
{
    while(x<MAX)
    {
        c[x]++;
        x+=lowbit(x);
    }
    
}
long long get(int x)
{
    long long sum=0;
    while(x>0)
    {
        sum+=c[x];
        x-=lowbit(x);
        
    }
    return sum;
}

int main()
{
    int ca,cas=1;
    scanf("%d",&ca);
    while(ca--)
    {
        scanf("%d%d%d",&N,&M,&K);
        memset(c,0,sizeof(c));
        memset(sts,0,sizeof(sts));
        for(int i=0;i<K;i++)
        {scanf("%d%d",&sts[i].x,&sts[i].y);
         sts[i].y++;}
        sort(sts,sts+K,cmp);
        update(sts[0].y);
        sum=0;
        for(int i=1;i<K;i++)
        {
            sum+=get(sts[i].y-1);//统计小于y,等价于统计<=y-1 
            update(sts[i].y);
        }
           printf("Test case %d: %lld\n",cas++,sum);

    }
    
}
posted on 2011-05-19 21:58  void-man  阅读(181)  评论(0)    收藏  举报