每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

Monoxer Programming Contest 2022(AtCoder Beginner Contest 238)(E,F)

Monoxer Programming Contest 2022(AtCoder Beginner Contest 238)(E,F)

E(图)

E

这个题大意就是给你一段区间和,问你可以根据这个区间和得到从1n的和

这个题都说是一个很明显的图论题,但是我一开始真的没看出来,看来是练习不够

题目每次给出的lr,可以看做把l1r看做一条边

我们最后只需要判断从0是否可以到达n即可

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define mem(a,b) memset((a),(b),sizeof(a))
const double eps=1e-9;
const int maxn=2e5+10;
const int mod=998244353;
int n,q;
vector<int>g[maxn];
bool vis[maxn];
void dfs(int u,int fa)
{
   if(vis[u]) return ;
   vis[u]=true;
   for (auto v:g[u])
   {
      if(v==fa) continue;
      dfs(v,u);
   }
   return ;
}
signed main() 
{
   cin>>n>>q;
   for (int i=1;i<=q;i++)
   {
      int l,r;
      cin>>l>>r;
      g[l-1].push_back(r);
      g[r].push_back(l-1);
   }
   dfs(0,-1);
   if(vis[n])
   {
      cout<<"Yes\n";
   }
   else 
   {
      cout<<"No\n";
   }
   system ("pause");
    return 0;
}

F(dp)

F

这个题大意就是有n个人,每个人都会有2次比赛,每次比赛都可以得到一个名次,然后我们会从这n个人中选择k个人,但是我们还有一个限制,如果a两场排名都比b高,如果选择了b,那么a也必须选中

问我们有多少种选人方式

这个dp蛮有意思的

dp[i][j][k]其中i代表我们已经安排好了前i个人,并且在这i中已经选择了j个人,其中k代表的是前i个人还没有被选中的人的最高的第二场排名(最小),那么对于下一个要选择的人,它必须比这个k还要好,必须赢了前面的那些未选择的人一轮(我们会按照第一轮从小到大的顺序来选择,这样,前面出现的一定比后面出现的排名高),不然,就会让前面的一些排名高的人赢了它两场,并且选了它,那么前面的人也会强制选中,不符合规律,而且也会打乱j(选中的人数),所以对于这一轮选中的这个人,必须比k还要小

对于不选i,我们还需要维护未选中的最高排名k,所以还要更新不选中之后的情况

对了,对于每一个都可选的情况(把k设置为n+1,这样都可以选了,也就是初状态,后面要一个都不留,k不会变,那么对于需要选择的人数和总人数都一样的情况很关键,最后不要漏了)

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define mem(a,b) memset((a),(b),sizeof(a))
const double eps=1e-9;
const int maxn=300+10;
const int mod=998244353;
int n,k;
int dp[maxn][maxn][maxn];
int a[maxn],b[maxn],rk[maxn];
signed main() 
{
   cin>>n>>k;
   for (int i=1;i<=n;i++)
   {
      cin>>a[i];
   }
   for (int i=1;i<=n;i++)
   {
      cin>>b[i];
      rk[a[i]]=b[i];
   }
   dp[0][0][n+1]=1;
   for (int i=1;i<=n;i++)
   {
      for (int j=0;j<=k;j++)
      {
         for (int last=0;last<=n+1;last++)//last=n+1的情况是都选
         {
            if(j<k&&rk[i]<last)
            //符合条件一定是逆序的,如果一场比赛赢了,那个下一个比赛就不可以再赢,不然会强制选中,dp每次都会记录选中的人数,一旦出现了这个问题,就很不好统计人数了,所以我们杜绝这个情况
            //我们这个是以第一场比赛的排名从小到大排序的,那么对于这一个人,如果想要被选中,
            //那么在一直第一场比赛失利的情况下(小),那么第二场就必须比之前所有未选中的人的排名还要高,这个我们只需要和最高排名的人比较即可
            {
               dp[i][j+1][last]=(dp[i][j+1][last]+dp[i-1][j][last])%mod;
            }
            int nxt=min(last,rk[i]);
            dp[i][j][nxt]=(dp[i][j][nxt]+dp[i-1][j][last])%mod;
         }
      }
   }
   int ans=0;
   for (int i=0;i<=n+1;i++)//都选,全选完了,一个不剩的情况
   {
      ans=(ans+dp[n][k][i])%mod;
   }
   cout<<ans<<"\n";
   system ("pause");
    return 0;
}
posted @   righting  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示