2019内蒙古大学生程序设计竞赛J

2019内蒙古大学生程序设计竞赛J
链接:https://www.bttcacm.cn/problem.php?id=1788

题目描述
平面上有 n 个点(任意两点的横坐标与纵坐标都不会相同),每个点向 x 轴 和 y 轴做垂线分别形成两个交点,两个交点和该点以及坐标原点构成一个矩形,并覆盖矩形内的点(在边缘上的点不算被覆盖),请输出平面上所有一次也没有被覆盖过的点。
输入格式
第一行一个正整数 T(T<=5),表示共有 T 组数据。
每组数据的第一行一个正整数数 n(1<=n<= 200000),表示平面上有 n 个点。
接下来 n 行每行两个正整数 x,y(1<=x,y<= 1e9)表示一个点的横纵坐标。
输出格式
按 x 轴坐标从小到大输出所有符合条件的点。
输入样例

1
5
8 1
17 5
9 6
12 11
13 7

输出样例

12 11
13 7
17 5


思路:感觉就是一个很简单的二维偏序的题目,不过之前选拔赛时卡了蛮多人好久的样子,其实就是按x从小到大排序,如果y相同的就把y小的排到前面,然后对每个点的y从前往后找,如果后面有的点的y大于这个点的y,那么这个点就会被覆盖,直接break到下一个循环再判断,如果没有比这个y还打的y了就输出这个点。
如果只是求二维偏序符合的点的个数有多少个的话可以采用树状数组求逆序对数量的方法来优化,排好x之后只用树状数组维护y的逆序对个数就好了,比如洛谷的:https://www.luogu.org/problemnew/show/U47402 ,AC代码也附在下面的下面。
有的题目不能过的话就把cin和cout改成scanf和printf,不同的oj对于这些输入输出的时间好像是有差距的。

AC代码:

#include<bits/stdc++.h>
#define INF 0x3F3F3F3F
#define endl '\n'
#define css(n) cout<<setiosflags(ios::fixed)<<setprecision(n); 
using namespace std;
typedef long long ll;
const int maxn=200005;
int n,m;
int t;
double a,b;
struct node
{
	int x,y;
}dian[maxn];
bool comp(node a,node b)
{
	if(a.x==b.x) return a.y<b.y;
	else return a.x<b.x;
}
int main()
{
	std::ios::sync_with_stdio(false);
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=0;i<n;i++)
		{
			cin>>dian[i].x>>dian[i].y;
		}
		sort(dian,dian+n,comp);
		for(int i=0;i<n;i++)
		{
			int flag=1;
			int z=dian[i].y;
			for(int j=i+1;j<n;j++)
			{
				if(dian[j].y>z)
				{
					flag=0;
					break;
				}
			}
			if(flag==1)
			{
				cout<<dian[i].x<<" "<<dian[i].y<<endl;
			}
		}
	}
	return 0;
} 

洛谷题AC代码:

#include<bits/stdc++.h>
#define INF 0x3F3F3F3F
#define endl '\n'
#define pb push_back
#define css(n) cout<<setiosflags(ios::fixed)<<setprecision(n); 
#define sd(a) scanf("%d",&a)
#define sld(a) scanf("%lld",&a)
#define m(a,b) memset(a,b,sizeof a)
#define p_queue priority_queue
using namespace std;
typedef long long ll;
const int maxn=100005;
int n,m;
int t;
double a,b;
int mxy;//y的最大值,也是树状数组的最大上限下标,记录下可以优化点时间。
struct node
{
	int x,y;
 }dian[maxn];
 bool comp(node a,node b)
 {
 	if(a.x==b.x) return a.y<b.y;
 	else return a.x<b.x;
 }
ll tre[maxn];
int lowbit(int x)
{
	return x&(-x);
}
void add(int pos,int val)
{
	while(pos<=mxy)
	{
		tre[pos]+=val;
		pos+=lowbit(pos);
	}
}
ll ask(int pos)
{
	ll ans=0;
	while(pos)
	{
		ans+=tre[pos];
		pos=pos-lowbit(pos);
	}
	return ans;
}
int main()
{
	sd(n);
	mxy=0;
	for(int i=1;i<=n;i++)
	{
		int a,b;
		sd(a);sd(b);
		dian[i].x=a;
		dian[i].y=b;
		mxy=max(mxy,b);
	 } 
	 sort(dian+1,dian+1+n,comp);
	 ll fin=0;
	 for(int i=1;i<=n;i++)
	 {
	 	int z=dian[i].y;
	 	fin+=ask(z);
	 	add(z,1);
	 }
	 printf("%lld\n",fin);
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值