zoukankan      html  css  js  c++  java
  • HZOJ 连连看

    考场几乎想到了正解,然而我也不知道当时在想啥,在没有证伪的情况下只是觉得无法实现就否了……

    最后打的好象是达哥说的O(4*15*n*m),复杂度不是很会证反正T成了暴力……


    题解:

    对于测试点8,9,10:bfs每个0的联通块,如果联通块边缘某累方块出现了x个,那么贡献为x*(x-1)/2。注意去掉既相邻又处于同一联通块的贡献。由于这些测试点的性质,统计出来的答案是正确的。

    推广到一般情况,上面的结论不是完全适用。

    考虑上面结论会错在什么地方,当两个方块同时属于多个0的联通块时会被算重,考虑容斥。(由于没有想到复杂度合适的实现方法考场止步于此)

    考虑给每个0的联通块编号,为了方便起见,设相邻两个同类方块之间也有一个0联通块。

    首先bfs求出每个非0点属于的0联通块,复杂度$O(nm)$。

    对于每类方块,求出f1[i]表示处于i联通块的个数,f2[i][j]表示处于i,j(可以有其他)的个数,f3[][][],f4[][][][]同理。

    之后就可以奇加偶减统计答案。

    然而数组并开不了那么大,考虑Hash_map.

    由于hash结构体并不是很好弄,于是我用了map,更容易理解,代码复杂度也更低一些。

    所以下面的代码极易被卡常。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<map>
    #define int LL
    #define pair pair<int,int>
    #define fir first
    #define sec second
    #define MP(a,b) make_pair(a,b)
    #define LL long long
    #define s1 (a.a<b.a)
    #define s2 (a.b<b.b)
    #define s3 (a.c<b.c)
    #define s4 (a.d<b.d)
    #define s5 (a.s<b.s)
    #define d1 (a.a==b.a)
    #define d2 (a.b==b.b)
    #define d3 (a.c==b.c)
    #define d4 (a.d==b.d)
    #define d5 (a.s==b.s)
    using namespace std;
    struct node1{int a,s;friend bool operator < (node1 a,node1 b){return d1?s5:s1;}};
    struct node2{int a,b,s;friend bool operator < (node2 a,node2 b){return d1?(d2?s5:s2):s1;}};
    struct node3{int a,b,c,s;friend bool operator < (node3 a,node3 b){return d1?(d2?(d3?s5:s3):s2):s1;}};
    struct node4{int a,b,c,d,s;friend bool operator < (node4 a,node4 b){return d1?(d2?(d3?(d4?s5:s4):s3):s2):s1;}};
    map<node1,int>mp1;
    map<node2,int>mp2;
    map<node3,int>mp3;
    map<node4,int>mp4;
    int n,m,k,mp[1010][1010];
    int bel[1010][1010],cnt;
    int t[1000010];
    bool v[1010][1010];
    int ix[5]={0,1,-1,0, 0};
    int iy[5]={0,0, 0,1,-1};
    vector<int> be[1010][1010];
    
    bool is(int x,int y,int sor){return x>0&&x<=n&&y>0&&y<=m&&mp[x][y]==sor;}
    bool ok(int x,int y){return x>0&&x<=n&&y>0&&y<=m&&mp[x][y]==0;}
    void bfs(int nx,int ny)
    {
    	bel[nx][ny]=cnt;
    	queue<pair >q;q.push(MP(nx,ny));
    	while(!q.empty())
    	{
    		int x=q.front().fir,y=q.front().sec;q.pop();
    		for(int i=1;i<=4;i++)
    		{	
    			int tx=x+ix[i],ty=y+iy[i];
    			if(ok(tx,ty)&&!bel[tx][ty])q.push(MP(tx,ty)),bel[tx][ty]=cnt;
    			else if(tx>0&&tx<=n&&ty>0&&ty<=m&&mp[tx][ty])be[tx][ty].push_back(cnt);
    		}
    	}
    }
    signed main()
    {
    //	freopen("ex_link3.in","r",stdin);
    //	freopen("in.txt","r",stdin);
    //	freopen("1.out","w",stdout);
    	
    	cin>>n>>m>>k;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			cin>>mp[i][j];
    	
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		if(!mp[i][j]&&!bel[i][j])++cnt,bfs(i,j);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			if(mp[i][j]&&is(i+1,j,mp[i][j]))be[i][j].push_back(++cnt),be[i+1][j].push_back(cnt);
    			if(mp[i][j]&&is(i,j+1,mp[i][j]))be[i][j].push_back(++cnt),be[i][j+1].push_back(cnt);
    		}
    		
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			sort(be[i][j].begin(),be[i][j].end());
    			int t=unique(be[i][j].begin(),be[i][j].end())-be[i][j].begin();
    			while(be[i][j].size()>t)be[i][j].pop_back();
    		}
    	
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		if(mp[i][j])
    		{
    			sort(be[i][j].begin(),be[i][j].end());int siz=be[i][j].size();
    			if(siz>=1){for(int k=0;k<siz;k++)mp1[(node1){be[i][j][k],mp[i][j]}]++;}
    			if(siz>=2){for(int k=0;k<siz;k++)for(int l=k+1;l<siz;l++)mp2[(node2){be[i][j][k],be[i][j][l],mp[i][j]}]++;}
    			if(siz>=3){for(int k=0;k<siz;k++)for(int l=k+1;l<siz;l++)for(int r=l+1;r<siz;r++)
    				mp3[(node3){be[i][j][k],be[i][j][l],be[i][j][r],mp[i][j]}]++;}
    			if(siz>=4){mp4[(node4){be[i][j][0],be[i][j][1],be[i][j][2],be[i][j][3],mp[i][j]}]++;}
    		}
    	map<node1,int>::iterator it1;
    	map<node2,int>::iterator it2;
    	map<node3,int>::iterator it3;
    	map<node4,int>::iterator it4;
    	LL ans=0;
    	for(it1=mp1.begin();it1!=mp1.end();it1++)ans+=it1->second*(it1->second-1)/2;
    	for(it2=mp2.begin();it2!=mp2.end();it2++)ans-=it2->second*(it2->second-1)/2;
    	for(it3=mp3.begin();it3!=mp3.end();it3++)ans+=it3->second*(it3->second-1)/2;
    	for(it4=mp4.begin();it4!=mp4.end();it4++)ans-=it4->second*(it4->second-1)/2;
    	printf("%lld
    ",ans);
    }
    	
    
  • 相关阅读:
    Java集合类: Set、List、Map、Queue使用场景梳理
    Java通过JDBC进行简单的增删改查(以MySQL为例)
    Servlet学习笔记
    Tomcat原理详解
    Tomcat的JVM和连接数设置
    Google Chrome 未响应。是否立即重新启动?---解决方法(秒速解决)
    LDAP服务器的概念和原理简单介绍
    Java IO流学习
    JavaScript_js模拟键盘输入
    Java_类似java.lang.VerifyError: Expecting a stackmap frame at branch target 22 in method的解决方法
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11695334.html
Copyright © 2011-2022 走看看