第一次打comet oj,菜
A 水題
C1
題意:類比油井問題,然後q次操作,把以(x1, y1)爲左上角和以(x2,y2)爲右下角的地圖置爲1,再找有多少個連通塊。
簡單版本的可以每次直接搜索,類似於油井問題
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5+10;
int dx[4][2] = {1,0,-1,0,0,1,0,-1};
int a[N], n, m;
char s[400][400];
bool vis[400][400];
bool ok(int x, int y)
{
if(x<0||x>=n||y<0||y>=m||vis[x][y]||s[x][y]!='1') return false;
return true;
}
void dfs(int x, int y)
{
vis[x][y] = 1;
for(int i = 0; i < 4; ++i)
{
int nx = x+dx[i][1], ny = y+dx[i][0];
if(ok(nx, ny))
dfs(nx, ny);
}
}
int test()
{
memset(vis, 0, sizeof(vis));
int ans = 0;
for(int i = 0; i < n; ++i)
for(int j = 0; j < m; ++j)
if(s[i][j] == '1'&&!vis[i][j]) {
ans++; dfs(i, j);
}
return ans;
}
void solve()
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
x1--; y1--; x2--; y2--;
for(int x = x1; x <= x2; ++x)
for(int y = y1; y <= y2; ++y)
s[x][y] = '1';
int ans = test();
printf("%d\n", ans);
}
int main ()
{
while(~scanf("%d%d", &n, &m)) {
for(int i = 0; i < n; ++i) scanf("%s", s[i]);
int t; scanf("%d", &t);
while(t--) solve();
}
return 0;
}
B
題意:一個地圖,一個字符串記錄移動方向,遇到蘋果,蛇身長加一,輸出移動後的地圖,撞牆就GG
我看很多大佬用的是隊列,其實我剛開始也想用的,後來發現數據範圍不是很大,用數組模擬的話也不會超內存,其實隊列更方便。於是我用slen當蛇頭,sw當蛇尾,當遇到蘋果時蛇頭進一,沒遇到就sw+1,蛇頭進一。注意吧喫過的蘋果置爲空就行,最後直接從sw到slen把蛇放上去,中間如果死亡,直接跳出。
#include <bits/stdc++.h>
using namespace std;
const int N = 4e5+10;
int dx[4][2] = {-1,0,0,-1,1,0, 0,1}; // wasd上下左右
int n, m, len, nx, ny, slen, sw;
map<char, int> mp;
char s[410][410], dir[N];
struct node
{
int x, y;
}a[N];
void init();
bool ok1(int x, int y);
bool ok(int x, int y)
{
if(x<0||x>=n||y<0||y>=m)
return false;
return true;
}
int main ()
{
init();
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i)
{
scanf("%s", s[i]);
for(int j = 0; j < m; ++j)
if(s[i][j] == '@') {
a[slen].x = i, a[slen++].y = j;
s[i][j] = '.';
}
}
scanf("%s", dir);
len = strlen(dir);
int flag = true; sw = 0;
for(int i = 0; i < len; ++i)
{
int x = a[slen-1].x, y = a[slen-1].y;
x += dx[mp[dir[i]]][0], y += dx[mp[dir[i]]][1];
if(!ok(x, y)) {
flag = false;
break;
}
if(s[x][y] == 'o') {
s[x][y] = '.';
a[slen].x = x;
a[slen++].y = y;
}
else
{
sw++;
a[slen].x = x;
a[slen++].y = y;
}
}
if(!flag) printf("GG\n");
else {
for(int i = sw; i < slen; ++i) {
s[a[i].x][a[i].y] = 'X';
if(i == slen-1)
s[a[i].x][a[i].y] = '@';
}
for(int i = 0; i < n; ++i) printf("%s\n", s[i]);
}
return 0;
}
void init()
{
slen = 0;
mp['W'] = 0; mp['A'] = 1;mp['S'] = 2; mp['D'] = 3;
}
bool ok1(int x, int y)
{
if(x<0||x>=n||y<0||y>=m||s[x][y]!='X')
return false;
return true;
}
C2
C1的困難版本,數據範圍大,顯然搜索已經不行了。不太會,我也是照着題解看的…
每個格子只會從0變成1,在從0變成1時訪問,並查級把每個位置對應的祖先設爲右邊最先爲0的列
另一個用來記錄個數
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int dx[4][2] = {1,0,-1,0,0,1,0,-1};
int n, m, ans, u, v;
char Map[1010][1010];
int id[1010][1010],Fa[1010][1010], book[N];
int Find(int *f, int x)
{
return f[x] == x?x:f[x] = Find(f, f[x]);
}
void solve(int x,int y)
{
static int tot = 0;
ans++; id[x][y] = ++tot; book[tot] = tot;
u = Find(Fa[x], y), v = Find(Fa[x], y+1);
if(u!=v) Fa[x][u] = v;
for(int i = 0; i < 4; ++i)
{
int nx = x+dx[i][0], ny = y+dx[i][1];
if(nx&&ny&&nx<=n&&ny<=m&&id[nx][ny])
{
u = Find(book, tot), v = Find(book, id[nx][ny]);
if(u!=v)
ans--, book[u] = v;
}
}
}
int main ()
{
freopen("in.txt", "r", stdin);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%s", Map[i]+1);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m+1; ++j)
Fa[i][j] = j;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(Map[i][j]=='1')
solve(i, j);
int t;
scanf("%d", &t);
while(t--) {
int x1,x2,y1,y2;
scanf("%d%d%d%d", &x1, &y1,&x2,&y2);
for(int x = x1; x <= x2; ++x)
for(int y = Find(Fa[x], y1); y <= y2; y = Find(Fa[x], y))
solve(x, y);
printf("%d\n", ans);
}
return 0;
}