Problem:
Problem H： Puzzle and Hexagons
Backgorund
超大人気ゲーム「パズル&ヘキサゴンズ」がついにリリースされた。このゲームは超面白すぎてドハマりする人が続出。あまりの熱中度に医師から中毒認定を受ける者も続出した。世界各国の有志達はこのゲームの中毒者達を助けるために「パズル&ヘキサゴンズ」のシミュレータを作り、危険な実機でのプレイを避けるよう促そうとした。あなたにはシミュレータ作りに協力して欲しい。
Problem
正六角形のマスを縦に
H
個、横に
W
個敷き詰めた盤面が与えられる。
Fig.1は
H
=4,
W
=7の時の盤面とそれに対応するマスの座標(
x
,
y
)を示す。
Fig.1
初期状態で各マスには色のついたブロックが存在する。
ブロックの色は以下のようにアルファベット一文字で表現される。
'R' ・・・赤
'G' ・・・緑
'B' ・・・青
'P' ・・・紫
'Y' ・・・黄
'E' ・・・水
次に操作の数
Q
が与えられる。
各操作では回転の中心座標(
x
,
y
)が与えられ、そのマスの周囲にある6つのブロックを時計回りに一つ回転させることを示す。(Fig.2 参照)。
このとき、ブロックが存在しないマスも空のブロックが存在すると考えて時計回りに一つ回転させる。
ただし、指定された座標とその周辺の６つのマスの内いずれか一つでも
H
×
W
の盤面の中に存在していない場合は回転を行わない。
Fig.2
次に以下の処理ができなくなるまで繰り返す。
Fig.3において、ブロックAの位置からB, C, Dの位置のいずれのマスにもブロックが存在しないとき、ブロックAはCの位置に落下する。マスB, Dが存在しない場合はブロックも存在しないと考え、マスCが存在しない場合は落下の処理を行わない。
1の処理が可能なブロックが存在する場合は1に戻る。
同じ色のブロックが3つ以上繋がっている場合、そのブロックは全て消滅する。
2つのブロックが繋がるとはマスの一辺を共有することである。
注意：この一連の処理は、操作が一つも与えられていない状態（初期状態）でも行われる。
Fig.3
全ての操作を実行した後の最終的な盤面を出力せよ。
Input
入力は以下の形式で与えられる。
H
W
F
0,
H−1
F
1,
H−1
…
F
W−1,
H−1
F
0,
H−2
F
1,
H−2
…
F
W−1,
H−2
.
.
.
F
0,
0
F
1,
0
…
F
W−1,
0
Q
x
0
y
0
x
1
y
1
.
.
.
x
Q−1
y
Q−1
1行目に、盤面の縦と横のサイズを表す2つの整数
H
と
W
が与えられる。
2行目から
H
+1行目に、各添字に対応する盤面の色を表す文字列が与えられる。
H
+2行目に、操作の数
Q
が与えられる。
続く
Q
行に回転の中心のマスの座標を表す
x
と
y
が与えられる。
Constraints
3 ≤
H
≤ 50
3 ≤
W
≤ 50
0 ≤
x
<
W
0 ≤
y
<
H
1 ≤
Q
≤ 100
F
i,
j
( 0 ≤
i
< W , 0 ≤
j
< H ) は'R','G','B','P','Y','E'のいずれかである。
Output
全ての操作を行った後の盤面を
H
行で出力せよ。
ただし、ブロックが無いマスは'.'で表すこと。
Sample Input1
3 3
RGR
RBP
YEB
1
1 1
Sample Output1
…
YBG
EBP
Fig.4はSample Input1における状態の遷移を表したものである。
Fig.4
Sample Input2
4 5
BYYGG
RRRRR
RRBRR
YYGGB
2
3 1
3 1
Sample Output2
.....
.....
.....
B.BGB
Sample Input3
4 4
BEEP
ERYY
BBRP
RBYP
1
1 2
Sample Output3
....
....
....
.B..
盤面の初期状態ですでに消えるブロックがあること注意。
両端にあるブロックの落下処理に注意。

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 55

enum Type{
	GU,
	KI,
};

int H,W;
int d_row[2][6] = {{-1,-1,0,1,0,-1},{-1,0,1,1,1,0}},d_col[2][6] = {{0,1,1,0,-1,-1},{0,1,1,0,-1,-1}};

char buf[SIZE][SIZE];
bool check[SIZE][SIZE];

bool rangeCheck(int row,int col){

	return row >= 0 && row <= H-1 && col >= 0 && col <= W-1;
}

//落下できるか判定
bool judgeFall(int row,int col){

	if(row == H-1){

		return false;
	}

	Type type = GU;
	if(col%2 == 1){

		type = KI;
	}

	for(int i = 2; i <= 4; i++){

		int adj_row = row+d_row[type][i];
		int adj_col = col+d_col[type][i];
		if(!rangeCheck(adj_row,adj_col))continue;

		if(buf[adj_row][adj_col] != '.'){

			return false;
		}
	}

	return true;
}

//落下処理
void funcFall(int row,int col){

	buf[row+1][col] = buf[row][col];
	buf[row][col] = '.';
}

//連結判定&消滅処理
bool funcDelete(){

	bool ret = false;

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){

			check[row][col] = false;
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(buf[row][col] == '.' || check[row][col])continue;

			check[row][col] = true;

			vector<pair<int,int>> vec;
			vec.push_back(make_pair(row,col));

			queue<pair<int,int>> Q;
			Q.push(make_pair(row,col));

			while(!Q.empty()){

				pair<int,int> tmp = Q.front();
				Q.pop();

				int tmp_row = tmp.first,tmp_col = tmp.second;

				Type type = GU;
				if(tmp_col%2 == 1){

					type = KI;
				}

				for(int i = 0; i < 6; i++){

					int adj_row = tmp_row+d_row[type][i];
					int adj_col = tmp_col+d_col[type][i];

					if(!rangeCheck(adj_row,adj_col) || (buf[adj_row][adj_col] != buf[tmp_row][tmp_col])
							|| check[adj_row][adj_col])continue;

					check[adj_row][adj_col] = true;
					vec.push_back(make_pair(adj_row,adj_col));
					Q.push(make_pair(adj_row,adj_col));
				}
			}

			if(vec.size() <= 2)continue;

			ret = true;

			for(int i = 0; i < vec.size(); i++){

				int tmp_row = vec[i].first;
				int tmp_col = vec[i].second;

				buf[tmp_row][tmp_col] = '.';
			}
		}
	}

	return ret;
}

void role(int row,int col){

	Type type = GU;
	if(col%2 == 1){

		type = KI;
	}

	string str = "";

	for(int i = 0; i < 6; i++){

		int adj_row = row+d_row[type][i];
		int adj_col = col+d_col[type][i];

		if(!rangeCheck(adj_row,adj_col))return;

		str += buf[adj_row][adj_col];
	}

	str = str.back()+str;
	str.pop_back();

	for(int i = 0; i < 6; i++){

		int adj_row = row+d_row[type][i];
		int adj_col = col+d_col[type][i];

		buf[adj_row][adj_col] = str[i];
	}
}


void calc(){

	while(true){

		//落下できるブロックが存在する間は、落下処理を行う
		while(true){

			vector<pair<int,int>> vec;
			//落下判定
			for(int row = 0; row < H-1; row++){
				for(int col = 0; col < W; col++){
					if(buf[row][col] != '.' && judgeFall(row,col)){

						vec.push_back(make_pair(row,col));
					}
				}
			}

			if(vec.size() == 0)break;

			//落下処理
			for(int i = 0; i < vec.size(); i++){

				funcFall(vec[i].first,vec[i].second);
			}
		}

		if(!funcDelete()){ //消滅ブロックなし

			break;
		}
	}
}


int main(){

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){

		scanf("%s",buf[row]);
	}

	//初期状態で処理
	calc();

	int numQ;
	scanf("%d",&numQ);

	int col,row;
	for(int i = 0; i < numQ; i++){

		scanf("%d %d",&col,&row);

		row = (H-1)-row;

		role(row,col);
		calc();
	}

	for(int row = 0; row < H; row++){

		printf("%s\n",buf[row]);
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3552
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 55

enum Type{
	GU,
	KI,
};

int H,W;
int d_row[2][6] = {{-1,-1,0,1,0,-1},{-1,0,1,1,1,0}},d_col[2][6] = {{0,1,1,0,-1,-1},{0,1,1,0,-1,-1}};

char buf[SIZE][SIZE];
bool check[SIZE][SIZE];

bool rangeCheck(int row,int col){

	return row >= 0 && row <= H-1 && col >= 0 && col <= W-1;
}

//落下できるか判定
bool judgeFall(int row,int col){

	if(row == H-1){

		return false;
	}

	Type type = GU;
	if(col%2 == 1){

		type = KI;
	}

	for(int i = 2; i <= 4; i++){

		int adj_row = row+d_row[type][i];
		int adj_col = col+d_col[type][i];
		if(!rangeCheck(adj_row,adj_col))continue;

		if(buf[adj_row][adj_col] != '.'){

			return false;
		}
	}

	return true;
}

//落下処理
void funcFall(int row,int col){

	buf[row+1][col] = buf[row][col];
	buf[row][col] = '.';
}

//連結判定&消滅処理
bool funcDelete(){

	bool ret = false;

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){

			check[row][col] = false;
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(buf[row][col] == '.' || check[row][col])continue;

			check[row][col] = true;

			vector<pair<int,int>> vec;
			vec.push_back(make_pair(row,col));

			queue<pair<int,int>> Q;
			Q.push(make_pair(row,col));

			while(!Q.empty()){

				pair<int,int> tmp = Q.front();
				Q.pop();

				int tmp_row = tmp.first,tmp_col = tmp.second;

				Type type = GU;
				if(tmp_col%2 == 1){

					type = KI;
				}

				for(int i = 0; i < 6; i++){

					int adj_row = tmp_row+d_row[type][i];
					int adj_col = tmp_col+d_col[type][i];

					if(!rangeCheck(adj_row,adj_col) || (buf[adj_row][adj_col] != buf[tmp_row][tmp_col])
							|| check[adj_row][adj_col])continue;

					check[adj_row][adj_col] = true;
					vec.push_back(make_pair(adj_row,adj_col));
					Q.push(make_pair(adj_row,adj_col));
				}
			}

			if(vec.size() <= 2)continue;

			ret = true;

			for(int i = 0; i < vec.size(); i++){

				int tmp_row = vec[i].first;
				int tmp_col = vec[i].second;

				buf[tmp_row][tmp_col] = '.';
			}
		}
	}

	return ret;
}

void role(int row,int col){

	Type type = GU;
	if(col%2 == 1){

		type = KI;
	}

	string str = "";

	for(int i = 0; i < 6; i++){

		int adj_row = row+d_row[type][i];
		int adj_col = col+d_col[type][i];

		if(!rangeCheck(adj_row,adj_col))return;

		str += buf[adj_row][adj_col];

		//printf("(%d,%d)%c\n",adj_row,adj_col,buf[adj_row][adj_col]);
	}

	str = str.back()+str;
	str.pop_back();

	//printf("str:%s\n",str.c_str());

	for(int i = 0; i < 6; i++){

		int adj_row = row+d_row[type][i];
		int adj_col = col+d_col[type][i];

		buf[adj_row][adj_col] = str[i];
	}
}


void calc(){

	while(true){

		//落下できるブロックが存在する間は、落下処理を行う
		while(true){

			vector<pair<int,int>> vec;
			//落下判定
			for(int row = 0; row < H-1; row++){
				for(int col = 0; col < W; col++){
					if(buf[row][col] != '.' && judgeFall(row,col)){

						vec.push_back(make_pair(row,col));
					}
				}
			}

			if(vec.size() == 0)break;

			//落下処理
			for(int i = 0; i < vec.size(); i++){

				funcFall(vec[i].first,vec[i].second);
			}
		}

		if(!funcDelete()){ //消滅ブロックなし

			break;
		}
	}
}

void debug(){

	for(int row = 0; row < H; row++){

		printf("%s\n",buf[row]);
	}
}


int main(){

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){

		scanf("%s",buf[row]);
	}

	//初期状態で処理
	calc();

	//debug();

	int numQ;
	scanf("%d",&numQ);

	int col,row;
	for(int i = 0; i < numQ; i++){

		scanf("%d %d",&col,&row);

		row = (H-1)-row;

		role(row,col);
		calc();
	}

	for(int row = 0; row < H; row++){

		printf("%s\n",buf[row]);
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3560
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

string col="RGBPYE";

int rx[2][6]={
	{0,-1,-1,0,1,1},
	{0,-1,-1,0,1,1},
};

int ry[2][6]={
	{-1,0,1,1,1,0},
	{-1,-1,0,1,0,-1},
};

int fx[2][3]={
	{-1,0,1},
	{-1,0,1},
};

int fy[2][3]={
	{0,-1,0},
	{-1,-1,-1},
};

int h,w;
int fie[51][51];

void print(){
	for(int i=0;i<h;i++){
		for(int j=0;j<w;j++){
			if(fie[h-1-i][j]==-1){
				printf(".");
			}else{
				printf("%c",col[fie[h-1-i][j]]);
			}
		}
		printf("\n");
	}
}

void rotate(int cx,int cy){
	for(int i=0;i<6;i++){
		int nx=cx+rx[cx%2][i];
		int ny=cy+ry[cx%2][i];
		if(nx<0 || nx>=w || ny<0 || ny>=h)return;
	}
	int n0x=cx+rx[cx%2][0];
	int n0y=cy+ry[cx%2][0];
	int tmp=fie[n0y][n0x];
	for(int i=5;i>=0;i--){
		int n1x=cx+rx[cx%2][i];
		int n1y=cy+ry[cx%2][i];
		int n2x=cx+rx[cx%2][(i+1)%6];
		int n2y=cy+ry[cx%2][(i+1)%6];
		fie[n2y][n2x]=fie[n1y][n1x];
	}
	int n1x=cx+rx[cx%2][1];
	int n1y=cy+ry[cx%2][1];
	fie[n1y][n1x]=tmp;
}

bool fall(int cx,int cy){
	for(int i=0;i<3;i++){
		int nx=cx+fx[cx%2][i];
		int ny=cy+fy[cx%2][i];
		if(nx>=0 && nx<w && ny>=0 && ny<h){
			if(fie[ny][nx]!=-1)return false;
		}
	}
	swap(fie[cy][cx],fie[cy-1][cx]);
	return true;
}

int cnt[2501];
int type[51][51];
bool used[51][51];

void dfs(int cx,int cy,int k){
	cnt[k]++;
	type[cy][cx]=k;
	used[cy][cx]=true;
	for(int i=0;i<6;i++){
		int nx=cx+rx[cx%2][i];
		int ny=cy+ry[cx%2][i];
		if(nx>=0 && nx<w && ny>=0 && ny<h){
			if(fie[ny][nx]==fie[cy][cx] && !used[ny][nx]){
				dfs(nx,ny,k);
			}
		}
	}
}

void process(){
	bool flag=true;
	while(flag){
		flag=false;
		bool flag2=true;
		while(flag2){
			flag2=false;
			for(int i=1;i<h;i++){
				for(int j=0;j<w;j++){
					if(fie[i][j]!=-1 && fall(j,i)){
						flag2=true;
					}
				}
			}
		}
		memset(cnt,0,sizeof(cnt));
		memset(used,false,sizeof(used));
		int sz=0;
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				if(fie[i][j]!=-1 && !used[i][j]){
					dfs(j,i,sz++);
				}
			}
		}
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				if(fie[i][j]!=-1 && cnt[type[i][j]]>=3){
					fie[i][j]=-1;
					flag=true;
				}
			}
		}
	}
}

int main(void){
	scanf("%d%d",&h,&w);
	memset(fie,-1,sizeof(fie));
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			for(int k=0;k<6;k++){
				if(col[k]==s[j]){
					fie[h-1-i][j]=k;
				}
			}
		}
	}
	process();
	int q;
	scanf("%d",&q);
	for(int i=0;i<q;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		rotate(a,b);
		process();
	}
	print();
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3312
final_rank: 5

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<queue>
using namespace std;

#define REP(i,N) for(int (i)=0;(i)<(N);(i)++)
constexpr int dh[6] = { 1,1,1,0,-1,0 };
constexpr int dw[6] = { -1,0,1,1,0,-1 };

constexpr int dh2[6] = { 0,1,0,-1,-1,-1 };
constexpr int dw2[6] = { -1,0,1,1,0,-1 };

int H, W, Q;
vector<string> F;
vector<pair<int, int>> xy;

bool isin(int h, int w) {
	return 0 <= h && h < H && 0 <= w && w < W;
}

void rotate(int h, int w) {
	REP(dir, 6) {
		int nh = h + (w % 2 == 1 ? dh : dh2)[dir];
		int nw = w + (w % 2 == 1 ? dw : dw2)[dir];
		if (!isin(nh, nw))return;
	}
	REP(dir, 5) {
		int nh = h + (w % 2 == 1 ? dh : dh2)[dir];
		int nw = w + (w % 2 == 1 ? dw : dw2)[dir];
		int nnh = h + (w % 2 == 1 ? dh : dh2)[dir + 1];
		int nnw = w + (w % 2 == 1 ? dw : dw2)[dir + 1];
		swap(F[nh][nw], F[nnh][nnw]);
	}
}

bool can_fall(int h, int w) {
	if (h == H - 1)return false;//下端
	REP(dir, 3) {
		int nh = h + (w % 2 == 1 ? dh : dh2)[dir];
		int nw = w + (w % 2 == 1 ? dw : dw2)[dir];
		if (!isin(nh, nw))continue;
		if (F[nh][nw] != '.')return false;
	}
	return true;
}

bool fall() {
	bool res = false;
	for (int h = H - 1; h >= 0; h--)REP(t, 2)REP(w, W) {
		if (w % 2 == t)continue; // ずれによる段数を考慮
		int nh = h;
		int nw = w;
		while (can_fall(nh, nw)) {
			swap(F[nh][nw], F[nh + 1][nw]);
			nh++;
			res = true;
		}
	}
	return res;
}

vector<pair<int, int>> feed(
	const int sh,
	const int sw,
	const char color,
	vector<vector<bool>>& see
) {
	vector<pair<int, int>> cands;
	queue<pair<int, int>> q;
	q.push({ sh,sw });
	see[sh][sw] = true;
	cands.push_back({ sh,sw });
	while (!q.empty()) {
		auto now = q.front(); q.pop();
		REP(dir, 6) {
			int w = now.second;
			int nh = now.first + (w % 2 == 1 ? dh : dh2)[dir];
			int nw = now.second + (w % 2 == 1 ? dw : dw2)[dir];
			if (!isin(nh, nw))continue;
			if (see[nh][nw])continue;
			if (F[nh][nw] == color) {
				see[nh][nw] = true;
				cands.push_back({ nh,nw });
				q.push({ nh,nw });
			}
		}
	}
	return cands;
}

bool erase() {
	bool res = false;
	vector<vector<bool>> see(H, vector<bool>(W, false));
	REP(h, H)REP(w, W)if (F[h][w] != '.' && !see[h][w]) {
		auto cands = feed(h, w, F[h][w], see);
		if (cands.size() < 3)continue;
		for (auto cand : cands)F[cand.first][cand.second] = '.';
		res = true;
	}
	return res;
}

void debug() {
	cout << "-----------------" << endl;
	for (auto row : F)cout << row << endl;
	cout << "-----------------" << endl;
}

void combo() {
	while (true) {
		if (!erase())break;
		//debug();
		if (!fall())break;
		//debug();
	}
}

int main() {
	cin >> H >> W;
	F.resize(H);
	REP(i, H)cin >> F[i];
	cin >> Q;
	REP(i, Q) {
		int x, y;
		cin >> x >> y;
		xy.push_back({ x,y });
	}
	//debug();
	combo();
	//debug();
	for (auto p : xy) {
		rotate(H - 1 - p.second, p.first);
		//debug();
		fall();
		//debug();
		combo();
		//debug();
	}
	for (auto row : F)cout << row << endl;
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3240
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
 
int n,m,q,a[51][51],dx[2][6]={{-1,-1,-1,0,1,0},{0,-1,0,1,1,1}},dy[6]={1,0,-1,-1,0,1};
bool u[51][51],u2[51][51];
bool check(int x, int y) {return (x>=0&&y>=0&&x<n&&y<m);}
 
int dfs(int x, int y, int k, bool o) {
  if(k!=a[x][y]) return 0;
  u[x][y]=u2[x][y]=true;
  if(o) a[x][y]=0;
  int sum=0;
  for(int i=0; i<6; i++) {
    if(check(x+dx[y%2][i],y+dy[i]) && !u2[x+dx[y%2][i]][y+dy[i]]) sum+=dfs(x+dx[y%2][i],y+dy[i],k,o);
  }
  return sum+1;
}
 
int main() {
  cin >> n >> m;
  for(int i=0; i<n; i++) {
    for(int j=0; j<m; j++) {
      char c;
      cin >> c;
      a[i][j]=(int)c;
    }
  }
  cin >> q;
  for(int t=0; t<=q; t++) {
    if(t) {
      int x,y;
      cin >> y >> x;
      x=n-x-1;
      int cnt=0;
      for(int i=0; i<6; i++) if(check(x+dx[y%2][i],y+dy[i])) cnt++;
      if(cnt==6) for(int i=0; i<5; i++) swap(a[x+dx[y%2][i]][y+dy[i]],a[x+dx[y%2][i+1]][y+dy[i+1]]);
    }
    while(1) {
      for(int i=n*2-1; i>=0; i--) {
        for(int j=i%2; j<m; j+=2) {
          int h=i/2;
          while(h<n-1 && a[h][j]) {
            for(int k=3; k<6; k++) if(check(h+dx[j%2][k],j+dy[k]) && a[h+dx[j%2][k]][j+dy[k]]) goto end;
            h++;
            swap(a[h][j],a[h-1][j]);
          }
        end:;
        }
      }
      bool ck=true;
      memset(u,0,sizeof(u));
      for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
          memset(u2,0,sizeof(u2));
          if(!u[i][j] && a[i][j] && dfs(i,j,a[i][j],0)>=3) {
            memset(u2,0,sizeof(u2));
            dfs(i,j,a[i][j],1);
            ck=false;
          }
        }
      }
      if(ck) break;
    }
  }
  for(int i=0; i<n; i++) {
    for(int j=0; j<m; j++) cout << (a[i][j]?(char)a[i][j]:'.');
    cout << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3124
final_rank: 4

code_snippet: /*
 * h.cc: 
 */

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>

using namespace std;

/* constant */

const int MAX_H = 50;
const int MAX_W = 50;

const int dxs[6] = {-1, 0, 1, 1, 0, -1};
const int dys[2][6] = {{0, -1, 0, 1, 1, 1}, {-1, -1, -1, 0, 1, 0}};

/* typedef */

typedef pair<int,int> pii;
typedef vector<pii> vpii;
typedef queue<pii> qpii;

/* global variables */

int h, w;
string flds[MAX_H];
bool used[MAX_H][MAX_W];

/* subroutines */

inline bool floating(int x, int y) {
  return
    (y > 0 && flds[y - 1][x] == '.' &&
     (x <= 0 || flds[y + dys[x & 1][0]][x - 1] == '.') &&
     (x >= w - 1 || flds[y + dys[x & 1][2]][x + 1] == '.'));
}

void fall_all() {
  for (int y = 1; y < h; y++) {
    for (int x = 1; x < w; x += 2)
      for (int y0 = y; flds[y0][x] != '.' && floating(x, y0); y0--)
	swap(flds[y0][x], flds[y0 - 1][x]);
    for (int x = 0; x < w; x += 2)
      for (int y0 = y; flds[y0][x] != '.' && floating(x, y0); y0--)
	swap(flds[y0][x], flds[y0 - 1][x]);
  }
}

bool vanish() {
  bool vnsh = false;
  memset(used, false, sizeof(used));

  for (int y0 = 0; y0 < h; y0++)
    for (int x0 = 0; x0 < w; x0++)
      if (flds[y0][x0] != '.' && ! used[y0][x0]) {
	vpii v;
	v.push_back(pii(x0, y0));
	qpii q;
	q.push(pii(x0, y0));
	char ch = flds[y0][x0];
	used[y0][x0] = true;

	while (! q.empty()) {
	  pii u = q.front(); q.pop();
	  int &ux = u.first, &uy = u.second;
	  for (int di = 0; di < 6; di++) {
	    int vx = ux + dxs[di], vy = uy + dys[ux & 1][di];
	    if (vx >= 0 && vx < w && vy >= 0 && vy < h &&
		! used[vy][vx] && flds[vy][vx] == ch) {
	      used[vy][vx] = true;
	      v.push_back(pii(vx, vy));
	      q.push(pii(vx, vy));
	    }
	  }
	}

	if (v.size() >= 3) {
	  for (vpii::iterator vit = v.begin(); vit != v.end(); vit++)
	    flds[vit->second][vit->first] = '.';
	  vnsh = true;
	}
      }

  return vnsh;
}

void do_proc() {
  do {
    fall_all();
  } while (vanish());
}

void print_flds() {
  for (int y = h - 1; y >= 0; y--) cout << flds[y] << endl;
}

/* main */

int main() {
  cin >> h >> w;
  for (int y = h - 1; y >= 0; y--) cin >> flds[y];

  do_proc();
  //print_flds();

  int q;
  cin >> q;
  while (q--) {
    int cx, cy;
    cin >> cx >> cy;
    if (cx <= 0 || cx >= w - 1 || cy <= 0 || cy >= h - 1) continue;

    char ctmp = flds[cy + dys[cx & 1][0]][cx + dxs[0]];
    for (int di = 1; di < 6; di++)
      flds[cy + dys[cx & 1][di - 1]][cx + dxs[di - 1]] =
	flds[cy + dys[cx & 1][di]][cx + dxs[di]];
    flds[cy + dys[cx & 1][5]][cx + dxs[5]] = ctmp;

    do_proc();
  }

  print_flds();
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 1220
final_rank: 2

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
using namespace std;

int dy[][6] = {{1, 1, 0, -1, 0, 1}, {1, 0, -1, -1, -1, 0}};
int dx[] = {0, 1, 1, 0, -1, -1};

void dropBlock(vector<string>& f)
{
    int h = f.size();
    int w = f[0].size();

    for(int y=1; y<h; ++y){
        for(int i=0; i<w; ++i){
            int x;
            if(i < w / 2)
                x = i * 2 + 1;
            else
                x = (i - w / 2) * 2;
            if(f[y][x] == '.')
                continue;

            int y2 = y;
            while(y2 > 0 && f[y2-1][x] == '.' && (x == 0 || f[y2+dy[x%2][4]][x-1] == '.') && (x == w - 1 || f[y2+dy[x%2][2]][x+1] == '.')){
                swap(f[y2][x], f[y2-1][x]);
                -- y2;
            }
        }
    }
}

bool eraseBlock(vector<string>& f)
{
    int h = f.size();
    int w = f[0].size();

    bool ans = false;
    vector<vector<bool> > check(h, vector<bool>(w, false));
    for(int y=0; y<h; ++y){
        for(int x=0; x<w; ++x){
            if(check[y][x] || f[y][x] == '.')
                continue;

            vector<pair<int, int> > v;
            queue<pair<int, int> > q;
            v.push_back(make_pair(y, x));
            q.push(make_pair(y, x));
            check[y][x] = true;
            while(!q.empty()){
                int y2 = q.front().first;
                int x2 = q.front().second;
                q.pop();

                for(int i=0; i<6; ++i){
                    int y3 = y2 + dy[x2%2][i];
                    int x3 = x2 + dx[i];
                    if(0 <= y3 && y3 < h && 0 <= x3 && x3 < w && !check[y3][x3] && f[y2][x2] == f[y3][x3]){
                        v.push_back(make_pair(y3, x3));
                        q.push(make_pair(y3, x3));
                        check[y3][x3] = true;
                    }
                }
            }

            if(v.size() >= 3){
                ans = true;
                for(unsigned i=0; i<v.size(); ++i)
                    f[v[i].first][v[i].second] = '.';
            }
        }
    }

    return ans;
}

void rotateBlock(vector<string>& f, int y, int x)
{
    int h = f.size();
    int w = f[0].size();
    if(y == 0 || y == h-1 || x == 0 || x == w-1)
        return;

    for(int i=5; i>0; --i){
        int y2 = y + dy[x%2][i];
        int x2 = x + dx[i];
        int y3 = y + dy[x%2][i-1];
        int x3 = x + dx[i-1];
        swap(f[y2][x2], f[y3][x3]);
    }
}

int main()
{
    int h, w;
    cin >> h >> w;

    vector<string> f(h);
    for(int i=h-1; i>=0; --i)
        cin >> f[i];

    int q;
    cin >> q;
    for(;;){
        do{
            dropBlock(f);
        }while(eraseBlock(f));

        if(--q < 0)
            break;

        int y, x;
        cin >> x >> y;
        rotateBlock(f, y, x);
    }
    
    for(int i=h-1; i>=0; --i)
        cout << f[i] << endl;

    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 1220
final_rank: 2

code_snippet: #include <algorithm>
#define IN(x,s,g) ((x) >= (s) && (x) < (g))
#define ISIN(x,y,w,h) (IN((x),0,(w)) && IN((y),0,(h)))

#include <queue>
#define REP(i,n) for(int i=0; i<(int)(n); i++)

#include <cstdio>
inline int getInt(){ int s; scanf("%d", &s); return s; }

#include <set>

using namespace std;

char b[64][64];
int w, h;

inline int id(int x, int y){
  return y * w + x;
}

int dx[6] = { 0, 1, 1, 0, -1, -1 };
int dy[2][6] = {
  { 1, 1, 0, -1, 0, 1 },
  { 1, 0, -1, -1, -1, 0 }
};

#define REPEX(x, y, xx, yy) \
 for(int _ = 0, xx, yy; (_ < 6) && ((xx = x + dx[_]), (yy = y + dy[x % 2][_]), true); _++)

int memo[64][64];

int dfs(int y, int x, int id){
  int ret = 1;
  memo[y][x] = id;
  REPEX(x, y, xx, yy) if(ISIN(xx, yy, w, h) && b[yy][xx] == b[y][x] && memo[yy][xx] == -1){
    ret += dfs(yy, xx, id);
  }
  return ret;
}

void printBoard(){
  REP(i,h){
    puts(b[h - i - 1]);
  }
}

bool erase(){
  bool ret = false;
  REP(i,h) REP(j,w) memo[i][j] = -1;
  int id = 0;
  vector<int> e(h * w);
  REP(i,h) REP(j,w) if(memo[i][j] == -1 && b[i][j] != '.'){
    const int cnt = dfs(i, j, id);
    if(cnt >= 3){ e[id] = 1; ret = true; }
    id++;
  }
  REP(i,h) REP(j,w) if(memo[i][j] != -1 && e[memo[i][j]])
    b[i][j] = '.';
  // printBoard(); REP(i,h){ REP(j,w) printf("%d ", memo[i][j]); puts(""); }
  return ret;
}

bool canDrop(int x, int y){
  for(int i = 2; i <= 4; i++){
    const int xx = x + dx[i];
    const int yy = y + dy[x % 2][i];
    if(ISIN(xx, yy, w, h) && b[yy][xx] != '.') return false;
  }
  return true;
}

bool drop(){
  bool ret = false;
  REP(i,h - 1){
    const int y = i + 1;
    for(int x = 1; x < w; x += 2){
      if(b[y][x] == '.') continue;
      int yy = y;
      while(yy > 0 && canDrop(x, yy)){ yy--; ret = true; }
      if(y != yy) swap(b[yy][x], b[y][x]);
    }
    for(int x = 0; x < w; x += 2){
      if(b[y][x] == '.') continue;
      int yy = y;
      while(yy > 0 && canDrop(x, yy)){ yy--; ret = true; }
      if(y != yy) swap(b[yy][x], b[y][x]);
    }
  }
  // printf("drop: %d\n", ret);
  return ret;
}

bool rotate(int x, int y){
  REPEX(x, y, xx, yy) if(!ISIN(xx, yy, w, h)) return false;

  for(int i = 0; i < 5; i++){
    const int p = (6 - i) % 6;
    const int q = (5 - i) % 6;
    swap(b[y + dy[x % 2][p]][x + dx[p]],
         b[y + dy[x % 2][q]][x + dx[q]]);
  }

  return true;
}

void process(){
  while(drop() || erase());
}

int main(){
  h = getInt(); w = getInt();
  REP(i,h) scanf("%s", b[h - i - 1]);

  process();
  const int q = getInt();
  REP(_,q){
    const int x = getInt();
    const int y = getInt();
    if(rotate(x, y)) process();
  }

  printBoard();
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1052
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define for_(i,a,b) for(int i=a;i<b;++i)
#define for_rev(i,a,b) for(int i=a;i>=b;--i)
#define rep(i,n) for(int i=0;i<(n);++i)
#define allof(a) a.begin(),a.end()
#define minit(a,b) memset(a,b,sizeof(a))
#define size_of(a) (int)a.size()

typedef long long lint;
typedef double Double;
typedef pair< int, int > pii;

int dx[6] = {0,1,1,0,-1,-1};

int dy[2][6] = {
	{1,1,0,-1,0,1},
	{1,0,-1,-1,-1,0}
};

int H, W, Q;
string hanic[55];

void rotate(int x, int y) {
	if (x == 0 || y == 0 || x == W - 1 || y == H - 1) return;
	
	int xp = x % 2;
	char piv = hanic[y + dy[xp][5]][x + dx[5]];
	
	for_rev(i,5,1) {
		hanic[y + dy[xp][i]][x + dx[i]] = hanic[y + dy[xp][i - 1]][x + dx[i - 1]];
	}
	
	hanic[y + dy[xp][0]][x + dx[0]] = piv;
}

void fall() {
	bool update = true;
	
	while (update) {
		update = false;
		
		for (int i = 1; i < H && !update; ++i)
		for (int j = 0; j < W && !update; ++j) {
			if (hanic[i][j] == '.') continue;
			
			bool fal = true;
			for_(d,2,5) {
				if (j == 0 && d == 4) continue;
				if (j == W - 1 && d == 2) continue;
				fal &= (hanic[i + dy[j % 2][d]][j + dx[d]] == '.');
			}
			
			if (fal) {
				hanic[i + dy[j % 2][3]][j + dx[3]] = hanic[i][j];
				hanic[i][j] = '.';
				update = true;
			}
		}
	}
}

bool vis[55][55];

void rec(int x, int y, char col, vector< pii >& vp) {
	vp.push_back(pii(x, y));
	vis[y][x] = 1;
	
	for_(d,0,6) {
		int nx = x + dx[d], ny = y + dy[x % 2][d];
		if (nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
		if (vis[ny][nx]) continue;
		if (hanic[ny][nx] == col) rec(nx, ny, col, vp);
	}
}

bool vanish() {
	minit(vis, 0);
	bool res = false;
	
	for_(y,0,H) for_(x,0,W) {
		if (!vis[y][x] && hanic[y][x] != '.') {
			vector< pii > vp;
		
			rec(x, y, hanic[y][x], vp);
			
			if (vp.size() >= 3) {
				for (size_t i = 0; i < vp.size(); ++i) {
					pii p = vp[i];
					hanic[p.second][p.first] = '.';
				}
				
				res = true;
			}
		}
	}
	
	return res;
}

int main() {
	cin >> H >> W;
	
	for_(i,0,H) cin >> hanic[H - i - 1];
	
	fall();
	while (vanish()) fall();
	
	cin >> Q;
	for_(i,0,Q) {
		int x, y;
		cin >> x >> y;
		rotate(x, y);
		fall();
		while (vanish()) fall();
	}
	
	for_(i,0,H) cout << hanic[H - i - 1] << endl;
}
accuracy: 1
time_ms: 80
memory_kb: 1216
final_rank: 7