2021.10.30考试总结[冲刺NOIP模拟19]

T1 特殊字符串

\(pjDP\)。设\(f_{i,j}\)为考虑到第\(i\)个字符,上一个字符为\(j\)的最大值。直接转移。

\(code:\)

T1
#include<bits/stdc++.h>
using namespace std;

namespace IO{
	typedef long long LL;
	int read(){
		LL x=0,f=1; char ch=getchar();
		while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
		while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
		return x*f;
	}
	void write(LL x,char sp){
		char ch[20]; int len=0;
		if(x<0) x=-x,putchar('-');
		do{ ch[len++]=x%10+'0'; x/=10; }while(x);
		for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
	}
	void ckmin(int& x,int y){ x=x<y?x:y; }
	void ckmax(LL& x,LL y){ x=x>y?x:y; }
} using namespace IO;

const int NN=100010;
int n,m;
LL k[26][26],f[NN][26],ans;
char s[NN];

signed main(){
	freopen("shiki.in","r",stdin);
	freopen("shiki.out","w",stdout);
	n=read();
	scanf("%s",s+1);
	m=read();
	for(int i=1;i<=m;i++){
		char c,h;
		cin>>c>>h;
		int tmp=read();
		k[c-'a'][h-'a']+=tmp;
	}
	memset(f,0xc0,sizeof(f));
	f[1][s[1]-'a']=0;
	for(int i=2;i<=n;i++){
		for(int j=0;j<26;j++)
			ckmax(f[i][j],f[i-1][j]);
		for(int j=0;j<26;j++)
			ckmax(f[i][s[i]-'a'],f[i-1][j]+k[j][s[i]-'a']);
	}
	write(f[n][s[n]-'a'],'\n');
	return 0;
}

T2 宝可梦

因为每个点间存在唯一简单路径,所以可达点的路径会形成一棵树,在图中行走会形成树的欧拉序。

于是从根走到根,欧拉序会形成一个环,加上题目限制方向(先右再前再左再后),可以发现环是唯一的。

接下来跑出这个环,\(O(1)\)出解。

\(code:\)

T2
#include<bits/stdc++.h>
using namespace std;

namespace IO{
	typedef long long LL;
	int read(){
		LL x=0,f=1; char ch=getchar();
		while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
		while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
		return x*f;
	}
	void write(int x,char sp){
		char ch[20]; int len=0;
		if(x<0) x=-x,putchar('-');
		do{ ch[len++]=x%10+'0'; x/=10; }while(x);
		for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
	}
	void ckmin(int& x,int y){ x=x<y?x:y; }
	void ckmax(int& x,int y){ x=x>y?x:y; }
} using namespace IO;

const int NN=500010;
int n,m,q,sx,sy,ex,ey,dr;
int step,stp[NN*2][5],apr[NN*2];
char dct,ch[NN];
bool mp[NN*2],to[NN*2][4];
int id(int x,int y){ return x*(m+2)+y; }

namespace operate{
	void move(int& x,int& y,int d){
		if(d==0) --x;
		if(d==1) ++y;
		if(d==2) ++x;
		if(d==3) --y;
	}
	void go(int& x,int& y,int& d){
		to[id(x,y)][d]=0; move(x,y,d);
		if(to[id(x,y)][(d+1)%4]) d=(d+1)%4;
		else if(to[id(x,y)][d]) d=d;
		else if(to[id(x,y)][(d+3)%4]) d=(d+3)%4;
		else if(to[id(x,y)][(d+2)%4]) d=(d+2)%4;
		stp[id(x,y)][d]=++step;
		if(x==ex&&y==ey) return;
		if(!apr[id(x,y)]) apr[id(x,y)]=step;
	}
	void search(){
		int x=0,y,dir;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++)
				if(mp[id(i,j)]){
					int tmp=to[id(i,j)][0]+to[id(i,j)][1]+to[id(i,j)][2]+to[id(i,j)][3];
					if(tmp==1){ x=ex=i; y=ey=j; break; }
				}
			if(x) break;
		}
		for(int i=0;i<4;i++) if(to[id(x,y)][i]){ dir=i; break; }
		do{ go(x,y,dir); }while(x!=ex||y!=ey);
	}
} using namespace operate;

signed main(){
	freopen("pokemon.in","r",stdin);
	freopen("pokemon.out","w",stdout);
	n=read(); m=read();
	for(int i=1;i<=n;i++){
		scanf("%s",ch+1);
		for(int j=1;j<=m;j++)
			mp[id(i,j)]=(ch[j]=='.');
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if(mp[id(i-1,j)]) to[id(i,j)][0]=1;
			if(mp[id(i,j+1)]) to[id(i,j)][1]=1;
			if(mp[id(i+1,j)]) to[id(i,j)][2]=1;
			if(mp[id(i,j-1)]) to[id(i,j)][3]=1;
		}
	search();
	q=read();
	while(q--){
		sx=read(); sy=read(); ex=read(); ey=read(); cin>>dct;
		if(sx==ex&&sy==ey){ puts("0"); continue; }
		dr=(dct=='U'?0:(dct=='R'?1:(dct=='D'?2:3)));
		int ans=1e9,st=id(sx,sy),ed=id(ex,ey);
		for(int i=0;i<4;i++)
			if(stp[st][dr]<stp[ed][i]) ckmin(ans,stp[ed][i]-stp[st][dr]);
		if(ans==1e9) ans=step-stp[st][dr]+apr[ed];
		write(ans,'\n');
	}
	return 0;
}

T3 矩阵

等比数列长度在有穷的情况下是\(\log\)的,直接搜就完了。

也可以考虑\(DP\),从权值小的点向权值大的点转移。

\(code:\)

T3
#include<bits/stdc++.h>
using namespace std;

namespace IO{
	typedef long long LL;
	int read(){
		LL x=0,f=1; char ch=getchar();
		while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
		while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
		return x*f;
	}
	void write(int x,char sp){
		char ch[20]; int len=0;
		if(x<0) x=-x,putchar('-');
		do{ ch[len++]=x%10+'0'; x/=10; }while(x);
		for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
	}
	void ckmin(int& x,int y){ x=x<y?x:y; }
	void ckmax(int& x,int y){ x=x>y?x:y; }
} using namespace IO;

const int NN=80010;
int n,m,ext,ans,mat[NN],f[NN][5],mul[NN][5];
struct node{
	int x,y,v;
	bool operator<(const node& a){
		return v<a.v;
	} 
}nod[NN];
int id(int x,int y){ return x*m+y; }
int get(int x,int y,int typ){
	if(typ==1) return id(x+1,y);
	if(typ==2) return id(x-1,y);
	if(typ==3) return id(x,y+1);
	if(typ==4) return id(x,y-1);
	return -1;
}

signed main(){
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	n=read(); m=read(); ans=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			mat[id(i,j)]=read();
			nod[++ext]=(node){i,j,mat[id(i,j)]};
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if(i>1) if(mat[id(i-1,j)]==mat[id(i,j)]) puts("-1"),exit(0);
			if(j>1) if(mat[id(i,j-1)]==mat[id(i,j)]) puts("-1"),exit(0);
		}
	memset(f,0xc0,sizeof(f));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if(i>1&&mat[id(i,j)]%mat[id(i-1,j)]==0)
				f[id(i,j)][1]=2, mul[id(i,j)][1]=mat[id(i,j)]/mat[id(i-1,j)];
			if(i<n&&mat[id(i,j)]%mat[id(i+1,j)]==0)
				f[id(i,j)][2]=2, mul[id(i,j)][2]=mat[id(i,j)]/mat[id(i+1,j)];
			if(j>1&&mat[id(i,j)]%mat[id(i,j-1)]==0)
				f[id(i,j)][3]=2, mul[id(i,j)][3]=mat[id(i,j)]/mat[id(i,j-1)];
			if(j<m&&mat[id(i,j)]%mat[id(i,j+1)]==0)
				f[id(i,j)][4]=2, mul[id(i,j)][4]=mat[id(i,j)]/mat[id(i,j+1)];
//			cout<<i<<' '<<j<<": "<<"U:"<<mul[id(i,j)][1]<<' '<<"L:"<<mul[id(i,j)][3]<<' '<<"D:"<<mul[id(i,j)][2]<<' '<<"R:"<<mul[id(i,j)][4]<<endl;
		}
	sort(nod+1,nod+ext+1);
	for(int i=1;i<=ext;i++)
		for(int j=1;j<=4;j++){
			int x=nod[i].x,y=nod[i].y,pos=id(x,y);
			if(!mul[pos][j]) continue;
			for(int k=1;k<=4;k++){
				if(x==n&&k==1) continue;
				if(x==1&&k==2) continue;
				if(y==m&&k==3) continue;
				if(y==1&&k==4) continue;
				int to=get(x,y,k);
				if(mul[pos][j]!=mul[to][k]) continue;
				ckmax(f[to][k],f[pos][j]+1);
			}
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int k=1;k<=4;k++)
					ckmax(ans,f[id(i,j)][k]);//,cout<<i<<' '<<j<<' '<<k<<' '<<f[id(i,j)][k]<<endl;
	write(ans,'\n');
	return 0;
}

T4 乘法

暂留

上一篇:mac下安装mysql 连接时候报错 ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)


下一篇:多校冲刺 NOIP 20211029 模拟 (18)