POJ 3067 Japan

转载请注明出处忆梦http://blog.csdn.net/yimeng2013/article/details/14518321



类型 : 单点修改,区间查询  

题目大意:日本的东岸和西岸有N,M座城市,按序号顺序的排列,K代表有K条铁路,每一条铁路的x,y分别代表东岸和西岸的一座城市。问这K条铁路一共有多少个交点。

题解一:先按x的降序排列,如果x相等则按照y的升序排列,那么对于(xi,yi)这条铁路来说前面有多少条铁路的y<yi && x != xi,那么就有几个交点。读者请自行动手演算一边。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1005
int c[N];
int n,m,t;
struct Node
{
	int x,y;
}node[N*N];

int lowbit(int x)
{
	return x & -x;
}

long long sum(int x)
{
	long long ret = 0;
	while(x > 0)
	{
		ret += c[x];
		x -= lowbit(x);
	}
	return ret;
}

void add(int x, int d)
{
	while(x < N)
	{
		c[x] += d;
		x += lowbit(x);
	}
}

int cmp(Node a, Node b)
{
	if(a.x == b.x)
		return a.y < b.y;
	return a.x > b.x;
}
int main ()
{
	int T;
	int Case = 1;
	scanf("%d", &T);
	while(T--)
	{
		memset(c, 0, sizeof(c));

		scanf("%d %d %d", &n, &m, &t);
		for(int i = 1; i <= t; i++)
		{
			scanf("%d %d", &node[i].x, &node[i].y);
		}

		sort(node+1,node+1+t,cmp);
		long long ans = 0;
		int temp = node[1].x;
		int cnt = 0;
		for(int i = 1; i <= t; i++)
		{
			if(temp != node[i].x)
			{
				temp = node[i].x;
				for(int j = i - 1; j >= i  - cnt; j--)
					add(node[j].y,1);
				
				ans += sum(node[i].y-1);
				cnt = 1;
			}

			else
			{
				cnt++;
				ans += sum(node[i].y-1);
			}

		}

		printf("Test case %d: ", Case++);
		printf("%lld\n", ans);
	}
}

题解二: 先将y按降序排列,如果y相等则按照x的升序排列,那么对于(xi,yi)这条铁路来说,前面有多少条铁路的x<xi,那么就有多少个交点。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 1005
using namespace std;
typedef struct
{
    int x;
    int y;
}NODE;
NODE a[MAXN*MAXN];
int c[MAXN];
int n,k,m;
bool cmp(NODE a,NODE b)
{
    if(a.y==b.y) return  a.x>b.x;
    return a.y>b.y;
}
int lowbit(int x)
{
    return x&-x;
}
void add(int x)
{
    while(x<=MAXN)
    {
        c[x]++;
        x+=lowbit(x);
    }
}
int sum(int x)
{
    long long  ret=0;
    while(x>0)
    {
        ret+=c[x];
        x-=lowbit(x);
    }
    return ret;
}
int main(void)
{
    int i,T,p=0;
    long long ans;
    scanf("%d",&T);
    while(T--)
    {
        printf("Test case %d: ",++p );
        scanf("%d%d%d",&n,&m,&k);
        for(i=1;i<=k;i++)
        scanf("%d%d",&a[i].x,&a[i].y);
        memset(c,0,sizeof(c));
        sort(a+1,a+k+1,cmp);
        ans=0;
        for(i=1;i<=k;i++)
         {
             ans+=sum(a[i].x-1);
             add(a[i].x);
         }
         printf("%lld\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值