此题暴力肯定过不了,会在第九个点 TLE。

暴力代码(#9 TLE)

代码就不写注释了,反正 AC 不了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<bits/stdc++.h>
using namespace std;
struct node{
int a,b;
}qj[114514],qjj[114514];
bool f[114514],ff,fff[114514],ffff[114514],g[114514];
int n,m,c,cc,jj;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>qj[i].a>>qj[i].b;
}
for(int i=1;i<=m;i++){
cin>>qjj[i].a>>qjj[i].b;
}
for(int i=1;i<=n;i++){
ff=0;jj=0;
for(int j=1;j<=m;j++){
if(qj[i].b==qjj[j].b){
if(!f[j]&&!ff){
c++;
f[j]=1;
jj=j;
ff=1;
}
if(qj[i].a==qjj[j].a&&!fff[j]){
if(!g[i]){
cc++;
g[i]=1;
}
f[jj]=fff[jj]=0;
f[j]=fff[j]=1;
jj=j;
}
}
}
}
cout<<c<<" "<<cc;
return 0;
}

提交记录。

正解

先看普通配对。

储存每个大小的笔的个数,$s_{i}$ 为大小为 $i$ 的笔的个数,后面再判断当前笔帽的大小是否有笔身可配对,有就将他们配对,然后将这支笔删掉。

再看优秀的配对。

将 map 的下标作为每个笔的哈希值,将大小和颜色作为参数进行计算,遇到相同哈希值的笔便 $map_{hash} + 1$ 此后如果有笔盖的哈希值与笔身的哈希值相等,就将他们配对,然后将这支笔删掉。

然后就没有然后了。

AC 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<bits/stdc++.h>
using namespace std;
long long N=1e5;
map<int,int> c;
int n,m,s[114514],a,b,a1,a2;//s为大小数组,a1为普通配对数,a2为优秀配对数
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a>>b;
s[b]++;
c[a+b*N]++;//计算哈希值
}//储存
for(int i=1;i<=m;i++){
cin>>a>>b;
if(s[b]!=0){
a1++;
s[b]--;
}//统计普通配对数
if(c[a+b*N]!=0){
a2++;
c[a+b*N]--;
}//统计优秀配对数
}
cout<<a1<<" "<<a2;
return 0;
}