UESTC 1951 LargeDumpling与1/N线段树
题目:http://www.qscoj.cn/#/problem/show/1951
逆向思考,先全部种上再一个一个删除
先把最外围都标记成空地,再bfs将所有的空地标记
剩下的不是空地也不是树的就是答案
删除的时候只有3种情况
1.周围都是空地 直接变成空地
2.周围没有空地 答案+1 变成答案区间
3.既有空地也有树 把连通块都变成空地
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int N=1e5+5;
const int M=2e3+5;
int x[N],y[N],a[M][M],ans[N],s;
bool use[M][M];
int fx[4]={0,0,-1,1};
int fy[4]={1,-1,0,0};
struct p
{
int x,y;
p(int xx,int yy)
{
x=xx;
y=yy;
}
};
void bfs()
{
memset(use,0,sizeof(use));
queue<p> que;
use[0][0]=1;
que.push(p(0,0));
while(!que.empty())
{
p t=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int tx=t.x+fx[i],ty=t.y+fy[i];
if (tx>=0&&tx<=2000&&ty>=0&&ty<=2000&&!use[tx][ty])
if (a[tx][ty]!=1)
{
a[tx][ty]=2;
que.push(p(tx,ty));
use[tx][ty]=1;
}
}
}
}
int check(int xx,int yy)
{
if (a[xx-1][yy]==2&&a[xx+1][yy]==2&&a[xx][yy+1]==2&&a[xx][yy-1]==2) return 1;
if (a[xx-1][yy]!=2&&a[xx+1][yy]!=2&&a[xx][yy+1]!=2&&a[xx][yy-1]!=2) return 2;
return 3;
}
void bfs1(int xx,int yy)
{
queue<p> que;
que.push(p(xx,yy));
while(!que.empty())
{
p t=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int tx=t.x+fx[i],ty=t.y+fy[i];
if (tx>=0&&tx<=2000&&ty>=0&&ty<=2000&&a[tx][ty]==0)
{
a[tx][ty]=2;
s--;
que.push(p(tx,ty));
}
}
}
}
int main()
{
int n;
memset(a,0,sizeof(a));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x[i],&y[i]);
x[i]+=1000;y[i]+=1000;
a[x[i]][y[i]]=1;
}
for(int i=0;i<=2000;i++)
{
a[0][i]=2;
a[i][0]=2;
a[i][2000]=2;
a[2000][i]=2;
}
bfs();
int tot=0;
s=0;
for(int i=0;i<=2000;i++)
for(int j=0;j<=2000;j++)
if (a[i][j]==0) s++;
ans[++tot]=s;
for(int i=n;i>1;i--)
{
int t=check(x[i],y[i]);
if (t==1)
a[x[i]][y[i]]=2;
else if (t==2)
{
a[x[i]][y[i]]=0;
s++;
}
else
{
a[x[i]][y[i]]=2;
bfs1(x[i],y[i]);
}
ans[++tot]=s;
}
for(int i=tot;i>=1;i--)
printf("%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号