题目
题解
本来在疑惑nlogn是不是正解,搜了搜这道题方法好像很多。
方法一:设K=max(A,B),K*K不MLE的话,可以O(n)做,即用cnt[i][j]记录从i换到j有多少个人。
方法二:这是我看到的一个方法,感觉很巧妙,使用swap,因为如果可行的话,存在a->b必定存在b->a,那么如果先构造一个序列放在c中 1 2 3 4 5 …每次读入一对a,b就swap(c[a],c[b]),如果最后序列还是1 2 3 4 5 ..就可行。很巧妙,但是我想说这种解法有问题比如两个需求1 2和1 2就挂掉了,如果能A只能说明数据太太太水辣!
方法三:自己想的nlogn,最易行的办法,直接扔一个结构体到set里面然后每次去找一找存不存在配对的就行了,不存在就扔进去,存在就计数并把配对的那个删掉。怀疑结构体会有点慢所以我定义
ci=(ai<<31)+bi
,这样用一个longlong就可以了,(有点像无冲突哈希?),时间感觉也不是很慢,130ms,突然想到也许用hashtable会快一些貌似能做到O(n)(雾)。
代码
方法三代码
//QWsin
#include<set>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=500000+10;
multiset<ll>dict;
int n,a[maxn],b[maxn];
inline ll cal(int a,int b){return ((1ll*a)<<31)+b;}
inline void solve()
{
for(int i=1;i<=n;++i) scanf("%d%d",a+i,b+i);
int cnt=0;
for(int i=1;i<=n;++i)
{
ll c=cal(b[i],a[i]);
if(dict.count(c)) cnt+=2,dict.erase(dict.find(c));
else dict.insert(cal(a[i],b[i]));
}
puts(cnt==n?"YES":"NO");
}
int main()
{
while(scanf("%d",&n)==1&&n) solve();
return 0;
}