这道题是我第一次算出来应该用什么复杂度写的题,或许是这一章刚介绍过,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;
}