洛谷P7568
设
设
如果
或者说
如果
或者说
如果
或者说
如果
那么
这几个方程都比较显然,请看清我们定的状态的表示的意义(特别是加黑的字体)后认真思考。
除了这几种情况,我们才需要进行简单模拟。
模拟一次的时间复杂度显然是
设当前时刻的上一个时刻的任务为
那么在经过这个任务后,所有人的总生命值就会减
显然总生命值为
那么这个模拟的过程最多有
所有总的时间复杂度为
滚动数组优化即可。
code有一些细节,详情见代码。
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int N=6e4+10,M=1010;
int n,m;
int u[N],v[N],f[M],life[M],ans[M],a[M];
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}
return x*f;
}
void attack(int time,int x)
{
for(int i=1;i<=m;i++)
a[i]=life[i];
a[v[time-1]]--;//注意这一行,因为我们的状态定义为上一个任务还没有执行,所以在模拟的时候要先把上一个任务执行了来
if(a[x])
a[x]--;
for(int i=time;i<=n;i++)
if(a[u[i]]&&a[v[i]]) a[v[i]]--;
int sum=0;
for(int i=1;i<=m;i++)
if(a[i]) sum++;
f[x]=sum;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
u[i]=read(),v[i]=read();
for(int i=1;i<=m;i++) life[i]=3;
for(int i=1;i<=m;i++)
attack(1,i);//预处理在1时刻之前杀每一个人
for(int i=1;i<=m;i++)
ans[f[i]]++;//先统计答案
for(int i=2;i<=n+1;i++)//枚举的当前时刻。由状态定义可知我们需要上一个时刻的任务。所以下面的代码i-1
{
for(int j=1;j<=m;j++)
if(j==u[i-1]&&life[u[i-1]]==1&&life[v[i-1]])
attack(i,j);//只有这一种情况需要模拟
for(int j=1;j<=m;j++)
ans[f[j]]++;//统计答案
if(life[u[i-1]]&&life[v[i-1]]) life[v[i-1]]--;//更新生命值
}
for(int i=0;i<=m;i++)
printf("%d ",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构