codeforces 993C Careful Maneuvering

xiaoxiao2021-02-28  43

题意 : 有两条平行于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; }

 

转载请注明原文地址: https://www.6miu.com/read-2622474.html

最新回复(0)