ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

nflsoj 20034 #12458.「NOIP2021模拟赛0929知临」棋盘

2021-10-04 11:01:11  阅读:258  来源: 互联网

标签:tmp 0929 22 int upd 12458 st 100010 nflsoj


小C有一个 $n $ 列的棋盘,一开始是空的,棋盘上可能会有一些障碍无法通过

小C要对它进行了 \(q\) 次操作,每次操作为以下三种操作之一

  1. Add:在棋盘末尾加入了一行
  2. Del:删除棋盘的第一行
  3. Que: 询问:有一只马从当前棋盘的第一行第ii列出发,要到最后一行第jj列。每次只能向棋盘的下方走,询问合法的方案数\(\mod 998244353\) .

**如果棋盘为空,起点或者终点有障碍,均输出 \(0\) **

一只马 \((x,y)\) 的活动范围是 \((x+1,y-2),(x+1,y+2),(x+2,y-1),(x+2,y+1)\)

\(1\leq n\leq 20,\ q\leq 100000\)

时限 : 1s

空限 : 1024mb

这个过程特别像双端队列,于是联想到上次模拟的一题,nflsoj 20034 #10232「2019五校联考-镇海3」小 ω 的仙人掌 .

可以用两个栈来维护 \(dp\) .

第一栈维护从后往前,第二个栈维护从前往后 .

但是,这个题目还有一个问题,就是马可以跳两层,需要维护两个 \(dp\) ,第一个是 \([l,x]\) 与 \([x+1,r]\) ,第二个是 \([l,x+1]\) 与 \([x+1,r]\) .

但是,计算的时候还是会算重,需要减掉重复的部分,就是从 \(x\) 行跳到 \(x+1\) 行的方案数 .

细节有亿点多 .

时间复杂度 : \(\mathrm O(qn^2)\)

空间复杂度 : \(\mathrm O(qn^2)\)

code

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int n,q;
string s[100010];
int f1[22][100010][22],g1[22][100010][22];
int f2[22][100010][22],g2[22][100010][22];
inline void upd(int &x,int y){x=(x+y)%mod;}
void nx(int g[22][100010][22],string board,int l,int tmp){
	for(int i=0;i<n;i++)for(int j=0;j<n;j++){
		g[i][tmp][j]=0;
		if(board[j]=='#')continue;
		if(j+2<n&&tmp-1>=l)upd(g[i][tmp][j],g[i][tmp-1][j+2]);
		if(j-2>=0&&tmp-1>=l)upd(g[i][tmp][j],g[i][tmp-1][j-2]);
		if(j+1<n&&tmp-2>=l)upd(g[i][tmp][j],g[i][tmp-2][j+1]);
		if(j-1>=0&&tmp-2>=l)upd(g[i][tmp][j],g[i][tmp-2][j-1]);
	}
}
void pr(int f[22][100010][22],int now,int st){
	for(int i=0;i<n;i++)for(int j=0;j<n;j++)f[i][now][j]=0;
	for(int i=0;i<n;i++)if(s[now][i]=='.')f[i][now][i]=1; 
	for(int i=0;i<n;i++)for(int k=now-1;k>=st;k--)for(int j=0;j<n;j++){
		f[i][k][j]=0;
		if(s[k][j]=='#')continue;
		if(k+1<=now&&j+2<n)upd(f[i][k][j],f[i][k+1][j+2]);
		if(k+1<=now&&j-2>=0)upd(f[i][k][j],f[i][k+1][j-2]);
		if(k+2<=now&&j+1<n)upd(f[i][k][j],f[i][k+2][j+1]);
		if(k+2<=now&&j-1>=0)upd(f[i][k][j],f[i][k+2][j-1]);
	}
}
int main(){
	freopen("chess.in","r",stdin);
	freopen("chess.out","w",stdout);
	cin>>n>>q;
	int st=1,ed=0,now=0;
	for(int t=0;t<q;t++){
		string type;
		cin>>type;
		if(type[0]=='A'){
			ed++;
			cin>>s[ed];
			if(st==ed){
				for(int i=0;i<n;i++)for(int j=0;j<n;j++){
					f1[i][st][j]=g1[i][st][j]=0;
				}
				for(int i=0;i<n;i++)if(s[ed][i]=='.')f1[i][st][i]=g1[i][st][i]=1;
				now=st;
			}else{
				nx(g1,s[ed],now,ed);
				if(st<now)nx(g2,s[ed],now-1,ed);
			}
		}else if(type[0]=='D'){
			st++;
			if(st>now){
				now=ed;
				if(st>ed)continue;
				for(int i=0;i<n;i++)for(int j=0;j<n;j++)g1[i][ed][j]=0;
				for(int i=0;i<n;i++)if(s[ed][i]=='.')g1[i][ed][i]=1;
				pr(f1,now,st);
				if(now>st){
					pr(f2,now-1,st);
					for(int i=0;i<n;i++)for(int j=0;j<n;j++)g2[i][now-1][j]=0;
					for(int i=0;i<n;i++)if(s[now-1][i]=='.')g2[i][now-1][i]=1;
					nx(g2,s[ed],now-1,ed);
				}
			}	
		}else{
			int x,y;
			cin>>x>>y;
			x--;y--;
			if(st>now)cout<<"0\n";
			else if(st==now)cout<<g1[x][ed][y]<<"\n";
			else{
				int ans=0;
				for(int i=0;i<n;i++){
					upd(ans,1ll*f1[i][st][x]*g1[i][ed][y]%mod);
					upd(ans,1ll*f2[i][st][x]*g2[i][ed][y]%mod);
				}
				for(int i=0;i<n;i++){
					if(i+2<n)upd(ans,(mod-1ll*f2[i][st][x]*g1[i+2][ed][y]%mod)%mod);
					if(i-2>=0)upd(ans,(mod-1ll*f2[i][st][x]*g1[i-2][ed][y]%mod)%mod);
				}
				cout<<ans<<"\n";
			}
		}
	}
	return 0;
}    

标签:tmp,0929,22,int,upd,12458,st,100010,nflsoj
来源: https://www.cnblogs.com/suadwm/p/15365962.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有