【补题计划】NOI Online 2021

【NOI Online 2021】补题记录

入门组

T1 【NOI Online 2021】切蛋糕

分类讨论啦!这个SB交了3遍才A

AC code

点击查看代码
#include<bits/stdc++.h>

using namespace std;

inline int read()
{
	int w=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9') { if(ch=='-'){ f=-1; } ch=getchar(); }
	while(ch>='0' && ch<='9') { w=(w<<3)+(w<<1)+(ch^48); ch=getchar(); }
	return w*f;
}

int t,a[4];

int main()
{
	t=read();
	while(t--)
	{
		for(int i=1;i<=3;i++) a[i]=read();
		
		sort(a+1,a+3+1);
		
		if(!a[1] && !a[2]) { cout<<0<<endl; continue; };
		if(!a[1] && (a[2]==a[3])) { cout<<1<<endl; continue; };
		if(!a[1] && (a[2]!=a[3])) { cout<<2<<endl; continue; };
		if(a[1]+a[2]==a[3]) { cout<<2<<endl; continue; };
		if((a[1]==a[2]) || (a[2]==a[3])) { cout<<2<<endl; continue; };
		cout<<3<<endl;
	}
	return 0;
}

T2 【NOI Online 2021】吃豆人

找规律+模拟のshabi题

AC code

点击查看代码
#include<bits/stdc++.h>

using namespace std;

const int maxn=1010;

int n,ans;

int val[maxn];

int a[maxn][maxn];

int same(int x,int y)
{
	if((y-x)&1) return 0;
	if(x==1 && y==n) return a[(y+1)/2][(y+1)/2];
	if(x==1) return a[(y+1)/2][(y+1)/2]+a[(2*n-y+1)/2][(2*n-y+1)/2];
	if(y==n) return a[(n-x)/2+1][(n+x)/2]+a[(n+x)/2][(n-x)/2+1];
	return a[(x+y)/2][(y-x)/2+1]+a[(y-x)/2+1][(x+y)/2]+a[n-(y-x)/2][n-(x+y)/2+1]+a[n-(x+y)/2+1][n-(y-x)/2];
}

int main()
{
	scanf("%d",&n);
	
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			int x,y;
			if(i+j<=n) x=i+j-1;
			else x=n+n-i-j+1;
			if(j>=i) y=j-i+1;
			else y=i-j+1;
			val[x]+=a[i][j];
			if(x!=y) val[y]+=a[i][j];
		}
	}
	
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
			ans=max(ans,val[i]+val[j]-same(i,j));
	
	printf("%d",ans);
	
	return 0;
}

T3 【NOI Online 2021】重力球

这题也切力!!!感觉思路很巧妙耶!

对于每一个地图,只有障碍点四周和边界四周是可以到达的

将其称为有效的点

我们可以将其以及其它点向四周行进应到达的对应的点预处理出来

不妨对其建反边(我们从重点——两个相遇的状态倒着往前推,所以要建反边)

然后用BFS跑一个类似于最短路的东西就好

代码稍稍有点长,可以适当压行

AC code

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<climits>
#include<algorithm>

using namespace std;

const int maxn=255;

const int maxm=2010;

inline int read()
{
	int w=0,f=1;
	char ch=getchar();
	while(ch<'0' || ch>'9')
	{
		if(ch=='-') f=-1;
                ch=getchar();
	}
	while(ch>='0' && ch<='9')
	{
		w=(w<<3)+(w<<1)+(ch^48);
		ch=getchar();
	}
	return w*f;
}

int n,m,q,tot,cnt;

int head[maxm][4];

int a[maxn][maxn];

int dis[maxm][maxm];

int x_1,x_2,y_1,y_2;

int id[maxn][maxn];

int to[maxm][maxm][4];

inline bool check(int i,int j) 
{
	return (a[i-1][j] || a[i+1][j] || a[i][j+1] || a[i][j-1]);
}

struct edge
{
	int to,next;
}e[maxm*maxm+5];

inline void add(int x,int y,int k)
{
	tot++;
	e[tot].to=y;
	e[tot].next=head[x][k];
	head[x][k]=tot;
}

inline void BFS()
{
	queue <pair<int,int> > q;
	for(int i=1;i<=cnt;i++)
		for(int j=1;j<=cnt;j++)
			dis[i][j]=INT_MAX;
	for(int i=1;i<=cnt;i++) 
	{
		q.push(make_pair(i,i)); dis[i][i]=1;
	}
	
	while(!q.empty())
	{
		pair<int,int> x=q.front(); q.pop();
		for(int k=0;k<=3;k++)
		{
			for(int i=head[x.first][k];i;i=e[i].next)
			{
				for(int j=head[x.second][k];j;j=e[j].next)
				{
					int to_1=e[i].to,to_2=e[j].to;
					if(dis[to_1][to_2]==INT_MAX)
					{
						dis[to_1][to_2]=dis[x.first][x.second]+1;
						q.push(make_pair(to_1,to_2));
					}
				}	
			}
		}
	}
}

inline int get_ans(int X1,int Y1,int X2,int Y2)
{
	return min(dis[to[X1][Y1][0]][to[X2][Y2][0]],min(dis[to[X1][Y1][1]][to[X2][Y2][1]],min(dis[to[X1][Y1][2]][to[X2][Y2][2]],dis[to[X1][Y1][3]][to[X2][Y2][3]])));
}

int main()
{
	n=read();m=read();q=read();
	
	for(int i=1;i<=m;i++)
	{
		int x=read();int y=read();
		a[x][y]=1;
	}
	
	for(int i=1;i<=n;i++) a[0][i]=a[n+1][i]=a[i][0]=a[i][n+1]=1;
	
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(!a[i][j] && check(i,j)) id[i][j]=++cnt;
	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j-1]) { to[i][j][0]=id[i][j]; }
			else { to[i][j][0]=to[i][j-1][0]; }
			if(a[i-1][j]) { to[i][j][1]=id[i][j]; }
			else { to[i][j][1]=to[i-1][j][1]; }
		}	
	}

	for(int i=n;i>=1;i--)
	{
		for(int j=n;j>=1;j--)
		{
			if(a[i][j+1]) { to[i][j][2]=id[i][j]; }
			else { to[i][j][2]=to[i][j+1][2]; }
			if(a[i+1][j]) { to[i][j][3]=id[i][j]; }
			else { to[i][j][3]=to[i+1][j][3]; }
		}
	}

	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(id[i][j])
			{
				for(int k=0;k<=3;k++) add(to[i][j][k],id[i][j],k);
			}
		}
	}
	
	BFS();
	
	while(q--)
	{
		x_1=read();y_1=read();
		x_2=read();y_2=read();
		if(x_1==x_2 && y_1==y_2)
		{
			cout<<0<<endl;  
		}
		else
		{
			int ans=get_ans(x_1,y_1,x_2,y_2);
			if(ans>=INT_MAX) cout<<-1<<endl;
			else cout<<ans<<endl;
		}
	}
	
	return 0;
}

提高组

T1 【NOI Online 2021】愤怒的小N

不可做题。。。

T2 【NOI Online 2021】积木小赛

这东西有点水啊。。。

A选的是子序列 B是子串

所以枚举B的子串,让A与B的子串匹配

把能配上的Hash值存到res数组里

然后对res去重就好啦

PS:模数取得有点大了,记得吸氧

AC code

点击查看代码
#include<bits/stdc++.h>

using namespace std;

const int maxn=3010;

const int base=51971;

const long long mod=2005091020050911;

int n,cnt;

char A[maxn];

char B[maxn];

long long res[maxn*maxn];

int main()
{
	scanf("%d%s%s",&n,A+1,B+1);
	
	for(int i=1;i<=n;i++)
	{
		long long mid=0; int p=1;
		for(int j=i;j<=n;j++)
		{
			while(p<=n && A[p]!=B[j]) p++;
			if(p>n) break;
			p++,cnt++;
			mid=(1ll*mid*base+B[j]-'a'+1)%mod;
			res[cnt]=mid;
		}
	}
	
	sort(res+1,res+cnt+1);
	
	cout<<unique(res+1,res+cnt+1)-res-1;
	
	return 0;
}

T3 【NOI Online 2021】岛屿探险

别想了,不会。。。

posted @ 2022-09-26 15:12  NinT_W  阅读(40)  评论(0编辑  收藏  举报