poj 3067 Japan(树状数组)

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

题目大意:给出t个样例

每个样例给出n个左边的点 m个右边的点 k条左边点连右边点的线

问最多有几个交点,每个交点最多有两条线经过

思路:

一:总体的思路

先来分析下什么样的情况两条线会有交点:即相交的情况必然是在在Li<Lj的情况下,Ri>Rj

所以我们先按照左边的由小到大的顺序排序,在对每条线查找右边点比他的个数

二:排序

struct node
{
	int s,e;
	bool operator <(const node &tmp)const
	{
		if(s==tmp.s)return e<tmp.e;
		return s<tmp.s;
	}
}nodes[MAXN];

即左边先按由小到大的顺序,当左边相等时,右边按由小到大的顺序.

因为,当左边点相等时,这两条线必定不可能相交,为了排除这种情况,当左边点相同时,让右边点小的先出现,这样就不会将左边点相同右边点比他大的直线记录进去!!

还有需要注意的是:

ret+=i-getSum(id);  因为是大于他的个数,所以转化为当前条数减去小于等于他的条数.

还有本题数据较大,需要将结果设为long long

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int MAXN =1000010;

struct node
{
	int s,e;
	bool operator <(const node &tmp)const
	{
		if(s==tmp.s)return e<tmp.e;
		return s<tmp.s;
	}
}nodes[MAXN];
int n,m,k;
int treenum[MAXN];

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

long long  getSum(int x){//一维
    long long  sum = 0;
    while(x){//将以x为根节点的数 相当于求其叶节点的和  但其非叶节点等于其两个子节点的和

        sum += treenum[x];
        x -= lowbit(x);
    }
    return sum;
}

void add(int x , int val){//一维
    while(x < MAXN){//相当于一个树  他将其自己以及他的父节点一路向上都加val
         treenum[x] += val;
         x += lowbit(x);
    }
}

long long  solve()
{
	memset(treenum,0,sizeof treenum);
	sort(nodes,nodes+k);
	long long ret=0;
	for(int i=0;i<k;i++)
	{
		int id=nodes[i].e;
		ret+=i-getSum(id);
		add(id,1);
	}
	return ret;
}
int main(){
	int t;
	scanf("%d",&t);
	for(int cas=1;cas<=t;cas++)
	{
		scanf("%d%d%d",&n,&m,&k);
		for(int i=0;i<k;i++)
		{
			scanf("%d%d",&nodes[i].s,&nodes[i].e);
		}
		printf("Test case %d: %lld\n" ,cas, solve());
	}
    return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值