zoukankan      html  css  js  c++  java
  • 洛谷 P5123 [USACO18DEC]Cowpatibility G

    洛谷 P5123 [USACO18DEC]Cowpatibility G

    洛谷传送门

    题目描述

    研究证明,有一个因素在两头奶牛能否作为朋友和谐共处这方面比其他任何因素都来得重要——她们是不是喜欢同一种口味的冰激凌!

    Farmer John 的 NN 头奶牛(2le Nle 5 imes 10^42≤N≤5×104)各自列举了她们最喜欢的五种冰激凌口味的清单。为使这个清单更加精炼,每种可能的口味用一个不超过 10^6106 的正整数 exttt{ID}ID 表示。如果两头奶牛的清单上有至少一种共同的冰激凌口味,那么她们可以和谐共处。

    请求出不能和谐共处的奶牛的对数。

    输入格式

    输入的第一行包含 NN。以下 NN 行每行包含 55 个整数(各不相同),表示一头奶牛最喜欢的冰激凌口味。

    输出格式

    输出不能和谐共处的奶牛的对数。


    题解:

    暴力还是又好想又好打,枚举任两个奶牛,进行对比,对比名单。随意维护,大约是(O(n^2 imes 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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13994920.html
Copyright © 2011-2022 走看看