uva 10763 Foreign Exchange(排序+二分查找)

这道题是我第一次算出来应该用什么复杂度写的题,或许是这一章刚介绍过,500000的数据必须用nlogn,所以我就

想到了二分,它的复杂度是logn,再对n个数据进行遍历,正好是nlogn,前两次TLE了,然后我就对我的做法没信心

了。。。看到一篇博客上说就应该这种方法,然后我就坚定的改自己的算法去了,哈哈,专注度没有达到五颗星,最多

三颗。。。

思路:

我用的是结构体保存的,先对每一对序列排序,然后对第二个元素在第一个元素中二分搜索,用到了

lower_bound,upper_bound,注释里面有写它的功能,其实这两个可以直接调用的。。。注意一下用

upper_bound的时候最后一个元素就ok啦。。。TLE其实不是我的算法的事,而是因为我把这两个函数写到循环里面

了,真傻。。。这样每次循环都会调用的。。。看网上有人说最后套数据n是小于1000的,加个if(n>1000)

for(;;;)就可以啦,哈哈,真聪明,我学会了。。。以后试着用一下。。

贴代码:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
struct node
{
	int i,j;
}a[500005];
int visit[500005];//用来标记是否已经配对过了
int n;
int cmp(const void *a,const void *b)//结构体的二级排序
{
	if(((node *)a)->i != ((node *)b)->i)
		return ((node *)a)->i - ((node *)b)->i;
	return ((node *)a)->j - ((node *)b)->j;
}
int lower_bound(int v)//二分查找,如果要查找的值存在的话,返回第一个等于该元素的位置,否则返回一个它要插入的第一个位置(序列必须先排序)
{
	int m,x = 1,y = n;
	while(x < y )
	{
		m = x + (y-x)/2;
		if(a[m].i >= v) y = m ;
		else
			x = m + 1;
	}
	return x;
}
int upper_bound(int v)//二分查找,如果存在该元素,就返回它的下一个位置(最后一个除外,就是说如果最后一个元素等于v,就返回的是n),如果不存在,就返回它插入后仍有序的序列
{
	int m;
	int x = 1;
	int y = n;
	while(x < y)
	{
		m = x +(y -x)/2;
		if(a[m].i<=v) x = m+1;
		else
			y = m;
	}
	return x;
}
int main()
{
	int i,j;
	while(cin >> n, n)
	{
		memset(visit,0,sizeof(visit));
		for(i=1; i<=n; i++)
		{
		//	cin >> a[i].i >> a[i].j;//cin输入流比较费时
			scanf("%d%d",&a[i].i,&a[i].j);
		}
		qsort(a+1,n,sizeof(a[0]),cmp);
	//	for(i=1; i<=n; i++)
	//	{
			//cin >> a[i].i >> a[i].j;
		//	scanf("%d%d",&a[i].i,&a[i].j);
	//		cout << a[i].i << " "<< a[i].j << endl;
	//	}
		int flag1 = 0;
		for(i=1; i<=n; i++)
		{
			if(visit[i] == 1)//配对过的不再访问
				continue;
			int flag = 0;
			int first = lower_bound(a[i].j);
			int last = upper_bound(a[i].j);
		//	cout << "first = " << first << " " << last << endl;
			if(a[first].i != a[i].j)//没有与之配对的直接退出输出NO
			{
				flag1 =1;
				break;
			}
			if(last == n)//把n的情况特判一下
				last ++;
			for(j=first; j<last; j++)
			{
				if(visit[j] == 1)
					continue;
				if(a[j].j == a[i].i)
				{
					visit[j] = 1;
					flag = 1;
					break;
				}
			}
			if(!flag)
			{
				flag1 = 1;
				break;
			}
			visit[i] = 1;
		}
		if(flag1)
			cout << "NO" << endl;
		//	puts("NO");
		else
			cout << "YES" << endl;
			//puts("YES");
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-03 14:07:13

uva 10763 Foreign Exchange(排序+二分查找)的相关文章

紫书第五章训练 uva 10763 Foreign Exchange by crq

Your non-profit organization (iCORE - international Confederation of Revolver Enthusiasts) coordinates a very successful foreign student exchange program. Over the last few years, demand has sky-rocketed and now you need assistance with your task.The

uva 10763 Foreign Exchange

给定n对信息,是1-->2有一对交换生,能交换的条件是2-->1也有一对交换生,问能否顺利交换. 思路:用有向图模拟,如果1-->2有一对,那么就优先判断2-->1有没人交换,有的话,就不用加边了,直接标记那条边用了即可. #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using n

uva:10763 - Foreign Exchange(排序)

题目:10763 - Foreign Exchange 题目大意:给出每个同学想要的交换坐标 a, b 代表这位同学在位置a希望能和b位置的同学交换.要求每一位同学都能找到和他交换的交换生. 解题思路:把给定的原先给定的序列,交换前后位置后得到新的序列.如果这个新的序列和原来的序列相同就符合要求.因为  (a,b) (b, a)若是成对出现,那么前后交换后还是(b, a)(a,b). 代码: #include <stdio.h> #include <string.h> #inclu

8.8 冒泡排序 选择排序 二分查找 递归使用

冒泡排序: #include <stdio.h> #include <stdlib.h> #include <time.h> #define N 100000 #define M 100000 void show_arr(int * a,int n) { int i; for(i = 0; i < n; i++) { printf("%d ",a[i]); } printf("\n"); } void init_arr(in

UVa 10539 (筛素数、二分查找) Almost Prime Numbers

题意: 求正整数L和U之间有多少个整数x满足形如x=pk 这种形式,其中p为素数,k>1 分析: 首先筛出1e6内的素数,枚举每个素数求出1e12内所有满足条件的数,然后排序. 对于L和U,二分查找出小于U和L的最大数的下标,作差即可得到答案. 1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 5 typedef long long LL; 6 7 const int maxn = 10

uva 10487 Closest Sums (遍历&amp;二分查找&amp;&amp;双向查找)

题目大意:先给定n个数字,现在要求算出这n个数字的两两之和保存到sum数组,然后在给定m个数,要求找到和每一个数最接近的sum[i]: 挨个计算每个属于其他数之间的sum,然后排序: 查找时有两种方法:二分查找&&双向查找:当然二分查找的效率比后者高了很多,但是都能AC. 提供一条新思路,并不一定非要用二分. 双向查找: #include<stdio.h> #include<algorithm> #include<stdlib.h> using name

I Count Two Three(打表+排序+二分查找)

I Count Two Three 二分查找用lower_bound 这道题用cin,cout会超时... AC代码: 1 /* */ 2 # include <iostream> 3 # include <cstring> 4 # include <string> 5 # include <cstdio> 6 # include <cmath> 7 # include <algorithm> 8 using namespace st

UVA - 10856 Recover Factorial(二分查找)

题目:(Sample Output是错的!要不是因为题目里面有描述输出,估计没人做的对吧) 这个题目,和这个OJ里面的另外一个题目有着紧密的联系.点击打开我的博客 (这一点,其实从标题也看的出来) 把这个题目的代码改改就能得到这个题目的代码. 在编代码的过程中就已经用到了二分了,可以确定,需要的数组大小的大致范围,大于2700000,小与2750000 代码: #include<iostream> using namespace std; int sum[2750000]; bool ispr

[FAFU 1266]STL排序+二分查找

http://acm.fafu.edu.cn/problem.php?id=1266 思路很容易理解: #include<cstdio> #include<algorithm> using namespace std; int num[1000000]; int main() { int n,m,a; while(~scanf("%d",&n)) { for(int i=0;i<n;++i) { scanf("%d",&