洛谷 P5123 [USACO18DEC]Cowpatibility G
洛谷 P5123 [USACO18DEC]Cowpatibility G
题目描述
研究证明,有一个因素在两头奶牛能否作为朋友和谐共处这方面比其他任何因素都来得重要——她们是不是喜欢同一种口味的冰激凌!
Farmer John 的 NN 头奶牛(2\le N\le 5\times 10^42≤N≤5×104)各自列举了她们最喜欢的五种冰激凌口味的清单。为使这个清单更加精炼,每种可能的口味用一个不超过 10^6106 的正整数 \texttt{ID}ID 表示。如果两头奶牛的清单上有至少一种共同的冰激凌口味,那么她们可以和谐共处。
请求出不能和谐共处的奶牛的对数。
输入格式
输入的第一行包含 NN。以下 NN 行每行包含 55 个整数(各不相同),表示一头奶牛最喜欢的冰激凌口味。
输出格式
输出不能和谐共处的奶牛的对数。
题解:
暴力还是又好想又好打,枚举任两个奶牛,进行对比,对比名单。随意维护,大约是\(O(n^2\times k)\),k是枚举常数,超时无疑。
然后考虑用map+bitset维护。但是要炸空间。
所以变成:用时间换空间。
每次10000,10000地暴力枚举。但是保证空间不炸。
代码:
#include<cstdio>
#include<bitset>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=50000+10;
const int maxm=250000+10;
int a[maxn][5],vis[maxn],mp[maxm],tot;
ll ans;
int n,m;
bitset<maxn+10> s[10010],t[10010];
void solve(int l,int r,int x,int y)
{
for(int i=x;i<=y;i++)
t[i-x].reset();
for(int i=l;i<=n;i++)
for(int j=0;j<5;j++)
if(x<=a[i][j]&&a[i][j]<=y)
t[a[i][j]-x][i]=1;
for(int i=l;i<=r;i++)
{
for(int j=0;j<5;j++)
if(x<=a[i][j]&&a[i][j]<=y)
t[a[i][j]-x][i]=0;
for(int j=0;j<5;j++)
if(x<=a[i][j]&&a[i][j]<=y)
if(!vis[i])
s[i-l]=t[a[i][j]-x],vis[i]=1;
else
s[i-l]|=t[a[i][j]-x];
}
}
int main()
{
//freopen("gentleman.in","r",stdin);
//freopen("gentleman.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=0;j<5;j++)
{
int x;
scanf("%d",&x);
a[i][j]=mp[++tot]=x;
}
sort(mp+1,mp+tot+1);
tot=unique(mp+1,mp+tot+1)-(mp+1);
for(int i=1;i<=n;i++)
for(int j=0;j<5;j++)
a[i][j]=lower_bound(mp+1,mp+tot+1,a[i][j])-mp;
for(int l=1,r;l<=n;l+=10000)
{
r=min(l+9999,n);
for(int x=1,y;x<=tot;x+=10000)
{
y=min(x+9999,tot);
solve(l,r,x,y);
}
for(int i=l;i<=r;i++)
ans+=s[i-l].count();
}
ans=1ll*n*(n-1ll)/2ll-ans;
printf("%lld\n",ans);
return 0;
}