游记
Day 0
打了所有的模板——发现忘记了单调队列的做法,复习了一下。
Day 0.5
睡了一个好觉。
Day 1
晴空万里,热得要命。
没有空调,只得认命。
比赛于14:30正式开始。提前5分钟开放,本蒟蒻熟悉了一下考场(换房间),然后打了一遍快速幂,之后比赛就开始了。
加油!GOGOGO!
D1T1
2分钟就切掉了,直接模拟即可。
D1T2
很显然是一道略简单的 (深搜)问题。
但是,要注意一下开 数组,表示当前节点有没有被深搜过。如果已经深搜过了,那么就不用看了;否则直接从该节点深搜下去,找到该星座的星星的数量,然后用一个数组统计一下即可。
代码比较长,比赛的时候打了30分钟,又调试了15分钟。总归心态还是不错的。
D1T3
刚刚看到这题,直发蒙。
什么鬼啊?直接用动归?怎么设计状态呢?
于是,我选择回来看D1T1与D1T2。
D1T1造了2组数据确认了一下,无误;
D1T2用并查集试了一试,两种程序对拍后无误;后来自己造了三组小数据,自己手算的与机算的一样,才回到D1T3。
为了求稳,我首先打了一个大暴力(50%都过不了)——直接枚举每张钱币被选的次数,时间复杂度直接上天。
接着,受到货币系统的启发,本蒟蒻开始打好一点的暴力。
#include <bits/stdc++.h>
using namespace std;
long long n,q,tot=0,t,maxq=0;
long long value[500005],tim[500005],question[500005],dp[500005];
struct node
{
bool getit;
int a[205];
}visited[500005];
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>>n>>q;
for (long long i=1;i<=n;i++)
{
value[i]=read(),tim[i]=read();
tot+=value[i]*tim[i];
visited[value[i]].getit=1;
visited[value[i]].a[value[i]]=1;
}
for (long long i=1;i<=q;i++)
{
cin>>question[i];
maxq=max(maxq,question[i]);
}
if (n<=10)
{
for (long long i=1;i<=maxq;i++)
{
visited[i].getit=0;
for (long long j=1;j<=n;j++) visited[i].a[j]=0;
}
for (long long i=1;i<=n;i++)
{
visited[value[i]].getit=1;
visited[value[i]].a[i]=1;
}
for (long long i=1;i<=maxq;i++)
{
if (visited[i].getit==0) continue;
for (long long j=1;j<=n;j++)
{
for (long long k=1;k<=tim[j]-visited[i].a[j];k++)
{
long long now=i+k*value[j];
if (now>maxq) break;
if (visited[i].a[j]+k>tim[j]) break;
else
{
visited[now].getit=1;
for (long long w=1;w<=n;w++) visited[now].a[w]=visited[i].a[w];
visited[now].a[j]=visited[i].a[j]+k;
}
}
}
}
}
}
估了一下时间复杂度,50%的数据是能过的。
同时,本蒟蒻突然发现——这不就是一个有限背包吗?!天哪,这么显然的东西这个时候才想到。
于是,果断开dp。然后与原来的程序(就是受货币系统启发的那个)对拍了一下,发现差不多;最后把两个程序合并为一个,即分段选择该用哪种方法。
然后就写出了最终的代码~
#include <bits/stdc++.h>
using namespace std;
long long n,q,tot=0,t,maxq=0;
long long value[500005],tim[500005],question[500005],dp[500005];
struct node
{
bool getit;
int a[205];
}visited[500005];
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>>n>>q;
for (long long i=1;i<=n;i++)
{
value[i]=read(),tim[i]=read();
tot+=value[i]*tim[i];
visited[value[i]].getit=1;
visited[value[i]].a[value[i]]=1;
}
for (long long i=1;i<=q;i++)
{
cin>>question[i];
maxq=max(maxq,question[i]);
}
if (n<=10)
{
for (long long i=1;i<=maxq;i++)
{
visited[i].getit=0;
for (long long j=1;j<=n;j++) visited[i].a[j]=0;
}
for (long long i=1;i<=n;i++)
{
visited[value[i]].getit=1;
visited[value[i]].a[i]=1;
}
for (long long i=1;i<=maxq;i++)
{
if (visited[i].getit==0) continue;
for (long long j=1;j<=n;j++)
{
for (long long k=1;k<=tim[j]-visited[i].a[j];k++)
{
long long now=i+k*value[j];
if (now>maxq) break;
if (visited[i].a[j]+k>tim[j]) break;
else
{
visited[now].getit=1;
for (long long w=1;w<=n;w++) visited[now].a[w]=visited[i].a[w];
visited[now].a[j]=visited[i].a[j]+k;
}
}
}
}
for (long long i=1;i<=q;i++)
{
t=question[i];
if (visited[t].getit==0) puts("No");
else if (visited[t].getit==1) puts("Yes");
}
return 0;
}
else
{
dp[0]=1;
for (long long i=1;i<=n;i++)
{
for (long long j=maxq;j>=value[i];j--)
{
if (dp[j]==1) continue;
long long flag=1;
for (long long k=j;k>=j-tim[i]*value[i];k-=value[i])
{
if (dp[k]==1)
{
flag=0;
break;
}
}
if (flag==0) dp[j]=1;
else dp[j]=0;
}
}
for (long long i=1;i<=q;i++)
{
if (dp[question[i]]==0) cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
return 0;
}
}
后来网崩了,过了好久才提交上去。结果这时电脑坑我,突然重启+更新+胡闹,让我不得不结束了这场比赛。
内心感觉要咕咕咕。
结果
预估分数: 100+100+100=300(怎么可能)
洛谷分数: 100+100+50=250(希望就这样吧)
实际分数: ___ + ____ + _____ = ______
撒花✿✿ヽ(°▽°)ノ✿撒花