题意 : 有两条平行于y轴的直线,他们是关于y轴对称的。每条直线上有一些点。每条直线上的点都与另外一条直线上的点连一条线,这条线与y轴有一个交点。选两个点,使经过这两个点的直线的两个端点数量最多。
每条直线上点的数量少于60。
有可能是最近状压做的比较多?突然就想到了二进制表示。
对于每个交点,有两个long long的数,因为64位完全可以放下。对于一个交点,一个数或上左边的坐标,一个或上右边的坐标。最后n^2枚举所有交点,取或,计算1的个数,取最大值即可。
不要忘记 ( 1LL<<i)。。。被坑了,debug才发现变成负的了,爆惹。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=4005;
ll l[maxn],r[maxn];
map<ll,ll> ans;
ll lc[maxn],rc[maxn];
ll getones(ll x)
{
ll ans=0;
while(x)
{
if(x%2)
ans++;
x/=2;
}
return ans;
}
int main()
{
ll n,m;
while(cin>>n>>m)
{
for(ll i=0;i<n;i++)
cin>>l[i];
for(ll j=0;j<m;j++)
cin>>r[j];
ans.clear();
memset(lc,0,sizeof(lc));
memset(rc,0,sizeof(rc));
ll cnt=1;
for(ll i=0;i<n;i++)
{
for(ll j=0;j<m;j++)
{
ll now=(l[i]+r[j]);
if(ans[now]==0)
{
ans[now]=cnt;
cnt++;
}
ll pos=ans[now];
lc[pos]|=(1LL<<i);
rc[pos]|=(1LL<<j);
}
}
ll res=0;
for(ll i=1;i<=cnt;i++)
{
for(ll j=1;j<=cnt;j++)
{
ll x=lc[i]|lc[j];
ll y=rc[i]|rc[j];
res=max(res,getones(x)+getones(y));
}
}
cout<<res<<endl;
}
return 0;
}