Japan

链接:http://poj.org/problem?id=3067

题目:Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <= 1000, N <= 1000). K superhighways will be build. Cities on each coast are numbered 1, 2, ... from North to South. Each superhighway is straight line and connects city on the East coast with city of the West coast. The funding for the construction is guaranteed by ACM. A major portion of the sum is determined by the number of crossings between superhighways. At most two superhighways cross at one location. Write a program that calculates the number of the crossings between superhighways.

题意:给两列数字,均为从上到下为1到n,再给它们之间的连线,求交点一共多少个(两两相交算一个)

分析:这道题利用的是计算的规律,题目里说到所给的数据是从小到大给的,但是我还是排了一下序,左列优先,右列次之,之后从最小的开始把右列的值放入树状数组,因为左列优先,所以之后的点对,只有在树状数组里存在别右列的值小的点才会有焦点,而且有几个就有几个焦点。

题解:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <functional>
#include <cmath>
#include <cctype>
#include <cfloat>
#include <climits>
#include <complex>
#include <deque>
#include <list>
#include <set>
#include <utility>
using namespace std;

__int64 ans;
int num[1000010];
int bit[1000010];
pair<int,int> ps[1000010];
int N,M,K;

void add(int x)
{
	while(x<=1000001){
		bit[x]+=1;
		x+=x&-x;
	}
}

__int64 countn(int x)
{
	__int64 an=0;
	while(x){
		an+=bit[x];
		x-=x&-x;
	}
	return an;
}

bool cmp(pair<int,int> a,pair<int,int> b)
{
	if(a.first==b.first) return a.second<b.second;
	else return a.first<b.first;
}

int main()
{
	//freopen("in.txt","r",stdin);
	int n;
	scanf("%d",&n);
	for(int T=1;T<=n;T++)
	{
		memset(bit,0,sizeof bit);
		ans=0;
		scanf("%d %d %d",&N,&M,&K);
		for(int i=1;i<=K;i++){
			scanf("%d %d",&ps[i].first,&ps[i].second);
		}
		sort(ps+1,ps+K+1,cmp);
		for(int i=1;i<=K;i++){
			ans+=countn(1000001)-countn(ps[i].second);
			add(ps[i].second);
		}
		printf("Test case %d: %lld\n",T,ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值