题解:
看完题解感觉好水,自己智障
将障碍反向运动,删掉扫过的点。
每个点维护四个方向的并查集,优化暴力就可以了。
code:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
struct node{
int x,y;
}a[10010];
int fa[5][2010][2010];
int n,m,e,q,ans,k;
bool del[2010][2010];
char ch[10];
void erase(int x,int y)
{
if(del[x][y]) return;
del[x][y]=true;
fa[0][x][y]--;
fa[1][x][y]++;
fa[2][x][y]--;
fa[3][x][y]++;
ans++;
}
int find01(int o,int x,int y)
{
if(fa[o][x][y]!=x) fa[o][x][y]=find01(o,fa[o][x][y],y);
return fa[o][x][y];
}
int find23(int o,int x,int y)
{
if(fa[o][x][y]!=y) fa[o][x][y]=find23(o,x,fa[o][x][y]);
return fa[o][x][y];
}
void up(int k)
{
for(int i=1;i<=e;i++)
{
int x=a[i].x,y=a[i].y;
a[i].x-=k;
if(y<1||y>m) continue;
if(x<1) continue;
if(x>n) x=n;
while(true)
{
x=find01(0,x,y);
if(x<1||x<a[i].x) break;
erase(x,y);
}
}
}
void down(int k)
{
for(int i=1;i<=e;i++)
{
int x=a[i].x,y=a[i].y;
a[i].x+=k;
if(y<1||y>m) continue;
if(x>n) continue;
if(x<1) x=1;
while(true)
{
x=find01(1,x,y);
if(x>n||x>a[i].x) break;
erase(x,y);
}
}
}
void left(int k)
{
for(int i=1;i<=e;i++)
{
int x=a[i].x,y=a[i].y;
a[i].y-=k;
if(x<1||x>n) continue;
if(y<1) continue;
if(y>m) y=m;
while(true)
{
y=find23(2,x,y);
if(y<1||y<a[i].y) break;
erase(x,y);
}
}
}
void right(int k)
{
for(int i=1;i<=e;i++)
{
int x=a[i].x,y=a[i].y;
a[i].y+=k;
if(x<1||x>n) continue;
if(y>m) continue;
if(y<1) y=1;
while(true)
{
y=find23(3,x,y);
if(y>m||y>a[i].y) break;
erase(x,y);
}
}
}
int main()
{
scanf("%d %d %d %d",&n,&m,&e,&q);
memset(del,false,sizeof(del));
for(int i=0;i<=n+1;i++)
for(int j=0;j<=m+1;j++)
fa[0][i][j]=fa[1][i][j]=i,fa[2][i][j]=fa[3][i][j]=j;
for(int i=1;i<=e;i++) scanf("%d %d",&a[i].x,&a[i].y),erase(a[i].x,a[i].y);
for(int i=1;i<=n;i++) a[++e].x=i,a[e].y=0,a[++e].x=i,a[e].y=m+1;
for(int i=1;i<=m;i++) a[++e].x=0,a[e].y=i,a[++e].x=n+1,a[e].y=i;
while(q--)
{
scanf("%s %d",ch+1,&k);
ans=0;
if(ch[1]=='U') down(k);
if(ch[1]=='D') up(k);
if(ch[1]=='L') right(k);
if(ch[1]=='R') left(k);
printf("%d\n",ans);
}
}