《Yuchang and Zixiang’s stones》

题意:简化下就是给定一个n * m的棋盘,有q组询问,每次询问棋子是否能放置在该位置。

能放置的条件就是,该位置之前没棋子,且该位置可以走到棋盘外。

Solution:

很明显这里是一个搜索类的问题,但是因为询问次数过多,如果对于每次询问都去搜索显然会超时。

考虑对询问离线:假定我们目前已经放置下了所有的棋子,并且处理出此时哪些位置可以走出棋盘外,哪些不能。然后我们倒序回去拆棋子。

当我们去拆这个棋子时,我们去查询它周围的点,是否可以走到棋盘外,若没有点可以,我们拆不拆除这个点都没有影响。

若周围有点可以,显然拆除后这个点也可以,那么我们拆除该点。

同时从这个点开始搜索,去更新之前无法走到,但是拆除这个点后可以走到的点。

基于上诉思路,可以发现每个点基本只会更新一次,那么时间复杂度平摊后为O(棋子数)。

可以发现此题可能存在一个点放置多次的情况,即我们回去处理的时候可能一个点处理多次,这个时候我只要去处理第一次放置这个位置的情况即可。

以下是这样处理的证明:

对于一个位置,如果它第一次放置时,就无法放置,那么显然后面再想去放置这个点更不可能可以放置,所以如果它不能放置,那么后面放置时都不会产生影响。

如果一个位置可以放置,那么当他放置后,这个位置后序将再无法放置,且很显然若这个位置可以放置,那么他放置的时间一定是最早的时间,所以对于第一次之后的放置。

也不会对结果产生影响。故只需要去最前面一次进行处理即可。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef __int128_t BIG;
typedef pair<int,int> pii;
const int N = 1e6 + 5;
const int M = 1e3 + 5;
const double eps = 1e-10;
const LL Mod = 4294967296;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;

int n,m,b[4][2] = {1,0,-1,0,0,1,0,-1};
int vis[M][M];
bool isget[M][M];
void Prework() {
    queue<pii> Q;
    memset(isget,0,sizeof(isget));
    for(int i = 1;i <= n;++i) {
        if(vis[i][1] == INF) {
            isget[i][1] = 1;
            Q.push(pii{i,1});    
        }
        if(vis[i][m] == INF) {
            isget[i][m] = 1;
            Q.push(pii{i,m});
        }
    }
    for(int i = 1;i <= m;++i) {
        if(vis[1][i] == INF) {
            isget[1][i] = 1;
            Q.push(pii{1,i});
        }
        if(vis[n][i] == INF) {
            isget[n][i] = 1;
            Q.push(pii{n,i});
        }
    }
    while(!Q.empty()) {
        pii q = Q.front();
        Q.pop();
        for(int i = 0;i < 4;++i) {
            int px = q.first + b[i][0];
            int py = q.second + b[i][1];
            if(px >= 1 && px <= n && py >= 1 && py <= m && isget[px][py] == 0 && vis[px][py] == INF) {
                isget[px][py] = 1;
                Q.push(pii{px,py});
            }
        }
    }
}
bool isdir(int i,int j) {
    if(i == 1 || i == n || j == 1 || j == m) return true;
    for(int k = 0;k < 4;++k) {
        int px = i + b[k][0];
        int py = j + b[k][1];
        if(px >= 1 && px <= n && py >= 1 && py <= m && isget[px][py] == 1) return true;
    }
    return false;
}
void cal(int sx,int sy,int id) {
    queue<pii> Q;
    Q.push(pii{sx,sy});
    while(!Q.empty()) {
        pii q = Q.front();
        Q.pop();
        for(int i = 0;i < 4;++i) {
            int px = q.first + b[i][0];
            int py = q.second + b[i][1];
            if(px >= 1 && px <= n && py >= 1 && py <= m && isget[px][py] == 0 && vis[px][py] > id) {
                isget[px][py] = 1;
                Q.push(pii{px,py});
            }
        }
    }
}
bool isu[M][M],tag[M][M];
int sum = 0,f = 0;
void dfs(int x,int y) {
    if(f) return ;
    if(x == 1 || x == n || y == 1 || y == m) f = 1;
    if(!tag[x][y]) {
        tag[x][y] = 1;
        for(int i = 0;i < 4;++i) {
            int px = x + b[i][0];
            int py = y + b[i][1];
            if(px >= 1 && px <= n && py >= 1 && py <= m && isu[px][py] == 0) dfs(px,py);
        }
    }
}
bool solve2(int sx,int sy) {
    f = 0;
    memset(tag,0,sizeof(tag));
    dfs(sx,sy);
    return f;
}
int x[N],y[N];
void solve() {
    while(~scanf("%d %d",&n,&m)) {
        int q;scanf("%d",&q);
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= m;++j) vis[i][j] = INF;
        for(int i = 1;i <= q;++i) {
            scanf("%d %d",&x[i],&y[i]);
          /*  if(solve2(x[i],y[i]) && isu[x[i]][y[i]] == 0) {
                printf("%d is put\n",i);
                sum++;
                isu[x[i]][y[i]] = 1;
            }*/
            vis[x[i]][y[i]] = min(i,vis[x[i]][y[i]]);
        }
        Prework();
        int ans = 0;
        for(int i = q;i >= 1;--i) {
            int dx = x[i],dy = y[i];
            if(i > vis[dx][dy]) continue;
            if(isdir(dx,dy)) {
                ans++;
                isget[dx][dy] = 1;
                cal(dx,dy,i);
            }
        }
        printf("%d\n",ans);
    }

}
int main() {
    solve();
  //  system("pause");
    return 0;
}
View Code

 

posted @ 2021-08-24 16:31  levill  阅读(48)  评论(0编辑  收藏  举报