[FZYZOJ 2132] Zrn神犇之一起来看流星雨

P2132 -- Zrn神犇之一起来看流星雨

时间限制:1000MS

内存限制:131072KB

Description

Zrn神犇带着妹纸来到异度空间看流星雨。

那儿有个矩形的星盘,一共有N*M格,流星雨都会落在那里。只是,那里的流星雨很奇特,都是很有节奏地、成排成排地落下的。每个时刻都会落下一排的流星,它们落在星盘上,形成了一个一个星群。

而Zrn神犇和妹纸对于星群的定义是不一样的。Zrn神犇认为,一颗星星和它周围的四个格子里的星星属于同一个星群。而妹纸认为,一颗星星和它周围的八个格子里的星星都属于同一个星群。

比如在第一个时刻,星盘上可能是这样的:

此时Zrn神犇和妹纸都看到了2个星群。

接着又落下了一排星星:

此时在Zrn神犇看来有2个星群,而在妹纸眼中只有1个星群。

又落下了第三排星星:

此时Zrn神犇看到的有3个星群,而在妹纸眼中依然只有一个星群。

 

妹纸看得有些累了,便靠在Zrn神犇的身上。Zrn神犇也伸出手臂,轻轻搂住她。

这时妹纸发话了:“你知道在任意时刻我们看到的星群数量各是多少吗?说不出来你亲我一下!”

Zrn神犇当然不想说啦!所以你就来算一下吧。

Input Format

第一行两个整数N,M

接下来一个N行M列的矩阵,表示在第N个时刻星盘上的布局,“*”表示该格有星星,“ ”表示该格没有星星。

下面一行一个整数Q,代表询问个数。

接下来Q行,每行一个正整数T,表示询问第T个时刻。

Output Format

输出Q行,对于每个T,输出一行两个整数,分别为在第T个时刻Zrn神犇看到的星群数量和妹纸看到的星群数量。

Sample Input

3 3
* *
 **
*  
3
1
2
3

Sample Output

2 2
2 1
3 1

Hint

#NMQ
1 10 10 1
2 2000 2000 1
3 3000 2000 2
4 50 50 50
5 40 40 5000
6 50 50 10000
7 1000 1000 50000
8 2000 2000 100000
9 5000 200 50000
10 20000 200 100000

保证1≤T≤N。

【题解】

就是并查集了,妹子的开一个,Zrn的开一个。

然后输入的时候进行维护,维护每个时段。

滚动数组进行优化。

并查集的时候我开同一个来进行操作=-=竟然T了!!!!!

然后我就分开来写,AC了=-=

我们需要分开来来优化。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int f[2][40000010],r[20001][2001],t[2],n,m,ans[2][20001],k;
 4 int getf0(int x) {return f[0][x]==x?x:f[0][x]=getf0(f[0][x]);}
 5 int getf1(int x) {return f[1][x]==x?x:f[1][x]=getf1(f[1][x]);}
 6 void join0(int a,int b) { 
 7     int fa=getf0(a),fb=getf0(b);
 8     if(fa!=fb) f[0][fa]=fb,t[0]--;
 9 }
10 void join1(int a,int b) { 
11     int fa=getf1(a),fb=getf1(b);
12     if(fa!=fb) f[1][fa]=fb,t[1]--;
13 }
14 int read() {
15     int x=0; int fx=1;
16     char ch=getchar();
17     while(ch<'0'||ch>'9') {if(ch=='-') fx=-1; ch=getchar();}
18     while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
19     return x*fx;
20 }
21 int main() {
22     n=read(),m=read();
23     for (int i=0;i<n;++i) {
24         for(int j=0;j<m;++j) {
25             char c=getchar();
26             if(c=='*') {
27                 ++k;
28                 f[0][k]=f[1][k]=r[i][j]=k;
29                 t[0]++,t[1]++;
30                 if(j&&r[i][j-1]) {
31                     join0(r[i][j],r[i][j-1]);
32                     join1(r[i][j],r[i][j-1]);
33                 }
34                 if(i&&r[i-1][j]) {
35                     join0(r[i][j],r[i-1][j]);
36                     join1(r[i][j],r[i-1][j]);
37                 }                
38                 if(i&&j&&r[i-1][j-1]) join1(r[i][j],r[i-1][j-1]);
39                 if(i&&j+1<m&&r[i-1][j+1]) join1(r[i][j],r[i-1][j+1]);
40             }
41         }
42         getchar();
43         ans[0][i]=t[0];
44         ans[1][i]=t[1];
45     }
46     int T,rx;
47     T=read();
48     while(T--) {
49         rx=read();rx--;
50         printf("%d %d\n",ans[0][rx],ans[1][rx]);
51     }    
52     return 0;
53 }
View Code

最后终于最变态的点优化到0.92s,还加了读入优化,不然就0.98s了吧=-=

 

posted @ 2015-06-09 17:28  TonyFang  阅读(319)  评论(0编辑  收藏  举报