这是我的一个大耻辱。
正是因此,时隔数月,我要重温这一切。
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 5∗1,5∗2,5∗4,5∗3。显然,在这四个物品中任意选择,一定能得到 5 × 1 , 5 × 2 … … 5 × 10 5×1, 5×2……5×10 5×1,5×2……5×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;
}