Subtask 1&2
很明显的暴力模拟,每到一个迷雾点,那就再后面更新符号,时间复杂度 O ( q 2 ) \operatorname{O}(q^2) O(q2)。
#include<iostream>
#include<algorithm>
#define MAXN 505
#define MAXM 200002
using namespace std;
int n,m,q,k,a[MAXM],b[MAXM];
char mp[MAXN][MAXN],c[MAXM];
int dy[4]={0,0,-1,1};
int dx[4]={1,-1,0,0};
inline int turn(char c){
if(c=='D'){
return 0;
}
if(c=='U'){
return 1;
}
if(c=='L'){
return 2;
}
return 3;
}
inline char change(char c){
if(c=='U'){
return 'D';
}
if(c=='D'){
return 'U';
}
if(c=='L'){
return 'R';
}
return 'L';
}
int main(){
scanf("%d %d %d %d",&n,&m,&q,&k);
for(int i=1;i<=n;++i){
scanf("%s",mp[i]+1);
}
for(int i=1;i<=q;++i){
scanf("\n%c %d %d",&c[i],&a[i],&b[i]);
}
int x=1,y=1;
for(int i=1;i<=q;++i){
x+=dx[turn(c[i])]*a[i];
y+=dy[turn(c[i])]*a[i];
x=min(max(x,1),n);
y=min(max(y,1),m);
// cout<<x<<" "<<y<<endl;
if(mp[x][y]=='X'){
for(int j=1;j<=b[i];++j){
c[i+j*k]=change(c[i+j*k]);
}
}
// for(int j=1;j<=q;++j){
// cout<<c[j]<<" ";
// }
// cout<<endl;
}
printf("%d %d",x,y);
return 0;
}
Subtask 3
考虑 k = 1 k=1 k=1 的情况,即每到一个迷雾点,就更新 [ i + 1 , i + b i ] [i+1,i+b_i] [i+1,i+bi],加上 1 1 1,当一个点它的值为偶数的时候,就会变回去,否则就要变。这个可以用维护差分数组的树状数组维护。时间复杂度 O ( q log q ) \operatorname{O}(q\log q) O(qlogq),仅限于 k = 1 k=1 k=1。
#include<iostream>
#include<algorithm>
#define MAXN 505
#define MAXM 200002
using namespace std;
int n,m,q,k,a[MAXM],b[MAXM];
char mp[MAXN][MAXN],c[MAXM];
int tree[MAXM<<1];
int dy[4]={0,0,-1,1};
int dx[4]={1,-1,0,0};
inline int turn(char c){
if(c=='D'){
return 0;
}
if(c=='U'){
return 1;
}
if(c=='L'){
return 2;
}
return 3;
}
inline char change(char c){
if(c=='U'){
return 'D';
}
if(c=='D'){
return 'U';
}
if(c=='L'){
return 'R';
}
return 'L';
}
inline int lowbit(int x){
return x&-x;
}
inline void modify(int p,int add){
for(int i=p;i<MAXM;i+=lowbit(i)){
tree[i]+=add;
}
}
inline int query(int p){
int ans=0;
for(int i=p;i;i-=lowbit(i)){
ans+=tree[i];
}
return ans;
}
inline void work(){
int x=1,y=1;
for(int i=1;i<=q;++i){
if(query(i)%2==1){
c[i]=change(c[i]);
}
x+=dx[turn(c[i])]*a[i];
y+=dy[turn(c[i])]*a[i];
x=min(max(x,1),n);
y=min(max(y,1),m);
if(mp[x][y]=='X'){
modify(i+1,1);
modify(i+b[i]+1,-1);
}
}
printf("%d %d",x,y);
}
int main(){
scanf("%d %d %d %d",&n,&m,&q,&k);
for(int i=1;i<=n;++i){
scanf("%s",mp[i]+1);
}
for(int i=1;i<=q;++i){
scanf("\n%c %d %d",&c[i],&a[i],&b[i]);
}
if(k==1){
work();
return 0;
}
int x=1,y=1;
for(int i=1;i<=q;++i){
x+=dx[turn(c[i])]*a[i];
y+=dy[turn(c[i])]*a[i];
x=min(max(x,1),n);
y=min(max(y,1),m);
if(mp[x][y]=='X'){
for(int j=1;j<=b[i];++j){
c[i+j*k]=change(c[i+j*k]);
}
}
}
printf("%d %d",x,y);
return 0;
}
Subtask 4&5
考虑到第 i i i 个节点只可能被 i − k , i − 2 × k , i − 3 × k … i-k,i-2\times k,i-3\times k\dots i−k,i−2×k,i−3×k… 更新到,也就是以 k k k 为模数, i i i 只可能更新到与其在模 k k k 意义下同余的点,考虑开 k k k 个树状数组,每一个维护 x × k + y = i x\times k+y=i x×k+y=i 中的 y y y, x x x 就是维护值的下标,时间复杂度 O ( q log q ) \operatorname{O}(q\log q) O(qlogq)。
#include<iostream>
#include<algorithm>
#include<cmath>
#define MAXN 505
#define MAXM 200002
#define MAXK 22
using namespace std;
int n,m,q,k,a[MAXM],b[MAXM];
char mp[MAXN][MAXN],c[MAXM];
int tree[MAXK][MAXM<<1];
int dy[4]={0,0,-1,1};
int dx[4]={1,-1,0,0};
inline int turn(char c){
if(c=='D'){
return 0;
}
if(c=='U'){
return 1;
}
if(c=='L'){
return 2;
}
return 3;
}
inline char change(char c){
if(c=='U'){
return 'D';
}
if(c=='D'){
return 'U';
}
if(c=='L'){
return 'R';
}
return 'L';
}
inline int lowbit(int x){
return x&-x;
}
inline void modify(int ex,int p,int add){
for(int i=p;i<MAXM;i+=lowbit(i)){
tree[ex][i]+=add;
}
}
inline int query(int ex,int p){
int ans=0;
for(int i=p;i;i-=lowbit(i)){
ans+=tree[ex][i];
}
return ans;
}
int main(){
scanf("%d %d %d %d",&n,&m,&q,&k);
for(int i=1;i<=n;++i){
scanf("%s",mp[i]+1);
}
for(int i=1;i<=q;++i){
scanf("\n%c %d %d",&c[i],&a[i],&b[i]);
}
int x=1,y=1;
for(int i=1;i<=q;++i){
int now=i/k;
if(query(i%k,now)%2==1){
c[i]=change(c[i]);
}
x+=dx[turn(c[i])]*a[i];
y+=dy[turn(c[i])]*a[i];
x=min(max(x,1),n);
y=min(max(y,1),m);
if(mp[x][y]=='X'){
modify(i%k,now+1,1);
modify(i%k,now+b[i]+1,-1);
}
}
printf("%d %d",x,y);
return 0;
}