NOI Online #3入门组题解

这是我的一个大耻辱。

正是因此,时隔数月,我要重温这一切。

Solution

T1

直接模拟即可。

T2

考虑搜索

我们对于每一个位置,如果它没有被访问过,就向外走,每走到一个格子就打一个标记,最后深搜完毕就得到了这一个星星的大小,然后开桶统计即可。

时间复杂度 O ( n m ) O(nm) O(nm)

T3

我们对于每一个物品 a i a_i ai,它有 b i b_i bi份,将它做二进制拆分。假设 a i = 5 , b i = 10 a_i=5, b_i=10 ai=5,bi=10,那么我们拆成了以下四个物品: 5 ∗ 1 , 5 ∗ 2 , 5 ∗ 4 , 5 ∗ 3 5*1, 5*2, 5*4, 5*3 51,52,54,53。显然,在这四个物品中任意选择,一定能得到 5 × 1 , 5 × 2 … … 5 × 10 5×1, 5×2……5×10 5×1,5×25×10这些数。

此时转化为了一个裸的 01 01 01背包,然后跑一遍 d p dp dp即可。每次可以 O ( 1 ) O(1) O(1)查询。

时间复杂度 O ( n log ⁡ m   t i + q ) O(n \log m\ t_i+q) O(nlogm ti+q),注意这里的 m m m表示物品数量的最大值。

另外,还有一种做法是单调队列,也是很裸的,留给读者自己思考。

Code

A

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

long long n,maxv=0;

struct node
{
	string name;
	string s;
	
	long long sos;
}a[100005];

signed main()
{
	cin>>n;
	for (long long i=1;i<=n;i++)  cin>>a[i].name>>a[i].s;
	for (long long i=1;i<=n;i++)
	{
		string now=a[i].s;
		long long cnt=0;
		if (now.size()<3)  continue;
		
		for (long long j=0;j<=now.size()-3;j++)
		{
			if (now[j]=='s'&&now[j+1]=='o'&&now[j+2]=='s')  cnt++;
		}
		maxv=max(maxv,cnt);
		a[i].sos=cnt;
	}
	for (long long i=1;i<=n;i++)
	{
		if (a[i].sos==maxv)  cout<<a[i].name<<' ';
	}
	cout<<endl<<maxv;
	
	return 0;
}

B

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

long long n,m,cnt=0,ans1=0,ans2=0;
long long visited[2005][2005],d[200005];
char a[2005][2005];

bool judge(long long ai,long long aj)
{
	if ((ai>=1&&ai<=n&&aj>=1&&aj<=m)&&a[ai][aj]=='*'&&visited[ai][aj]==0)  return true;
	else return false;
}

inline void dfs(long long ii,long long jj)
{
	visited[ii][jj]=1;
	cnt++;
	
	if (judge(ii-1,jj-1))  dfs(ii-1,jj-1);
	if (judge(ii-1,jj))  dfs(ii-1,jj);
	if (judge(ii-1,jj+1))  dfs(ii-1,jj+1);
	
	if (judge(ii,jj-1))  dfs(ii,jj-1);
	if (judge(ii,jj+1))  dfs(ii,jj+1);
	
	if (judge(ii+1,jj-1))  dfs(ii+1,jj-1);
	if (judge(ii+1,jj))  dfs(ii+1,jj);
	if (judge(ii+1,jj+1))  dfs(ii+1,jj+1);
	
	return;
}

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

signed main()
{
	cin.tie(0); 
	
	n=read(),m=read();
	for (long long i=1;i<=n;i++)
	{
		for (long long j=1;j<=m;j++)  cin>>a[i][j];
	}
	for (long long i=1;i<=n;i++)
	{
		for (long long j=1;j<=m;j++)
		{
			if (a[i][j]=='.')  continue;
			if (visited[i][j]==1)  continue;
			
			cnt=0;
			dfs(i,j);
			d[cnt]++;
		}
	}
	for (long long i=1;i<=200000;i++)
	{
		if (d[i]>0)
		{
			ans2=max(ans2,d[i]*i);
			ans1++;	
		}
	}
	cout<<ans1<<' '<<ans2<<endl;
	
	return 0;
}

C

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

int n,m,pos=0,len=0;
int a[500005],b[500005],c[500005],q[500005];
bool dp[50000005];

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

signed main()
{
	cin>>n>>m;
	for (int i=1;i<=n;i++)  cin>>a[i]>>b[i];
	for (int i=1;i<=n;i++)
	{
		int x=b[i];
		for (int j=0;j<10;j++)
		{
			int p=(1<<j);
			if (x>=p)  c[++pos]=a[i]*p,x-=p;
			else
			{
				if (x)  c[++pos]=a[i]*x;
				break;
			}
		}
	}
	for (int i=1;i<=m;i++)  q[i]=read(),len=max(len,q[i]);
	dp[0]=1;
	
	for (int i=1;i<=pos;i++)
	{
		for (int j=len;j>=c[i];j--)  dp[j]=dp[j]|dp[j-c[i]];
	}
	for (int i=1;i<=m;i++)
	{
		if (dp[q[i]])  puts("Yes");
		else puts("No");
	}
	return 0;
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页