当前位置: 首页 > news >正文

2025icpc网络赛第一场The 2025 ICPC Asia East Continent Online Contest (I)

题目链接:The 2025 ICPC Asia East Continent Online Contest (I) - Dashboard - Contest - QOJ.ac

G. Sorting

思路

保证有所有的 a->a+1 就输出yes,赛时写dfs结果T了一发

代码

void solve(){int n,m;cin>>n>>m;vb vis(n+1,false);vis[1]=true;for(int i=1;i<=m;i++){int a,b;cin>>a>>b;if(b==a+1) vis[b]=true;}int x=1;while(x<=n&&vis[x]==true) x++;if(x==n+1){cout<<"Yes\n";}else{cout<<"No\n";}
}

B. Creating Chaos

思路

我们可以将gcd(|i-j|,n)的所有值看成一个二维的表格,我们只需要贪心地选出前k个行和列之和最大的即可,考虑如果抛弃i之后那么所有的关于i这一行和列的数需要都删除,我们要不断维护其值即可

补题的时候发现其实只需要输出连续的k个数即可(这是为什么呢?)

代码

#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;void solve(){int n,k;cin>>n>>k;vector<pll> res;for(int i=1;i<=n;i++){int x=0;for(int j=1;j<=n;j++){x+=__gcd(abs(i-j),n);}res.push_back({x,i});}vi ans(k+1);for(int i=1;i<=k;i++){sort(res.begin(),res.end());auto [v,id]=res.back();res.pop_back();ans[i]=id;for(int j=0;j<res.size();j++){res[j].first-=__gcd(abs(res[j].second-id),n);}}for(int i=1;i<=k;i++){cout<<ans[i]<<" \n"[i==k];}
}signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;// cin>>_;while(_--) solve();return 0;
}

I. Knapsack Problem

思路

把玩几个样例吧,能够得到从i到j走,和从j到i走所需的背包数量其实是一样的,那么我们就可以从T点出发跑一遍最短路即可,优先队列维护背包数量和背包剩余容量即可

代码

#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;struct node{int cnt,id,r;   //数量,节点,剩余容量
};
struct cmp{bool operator()(const node &x,const node &y){if(x.cnt==y.cnt) return x.r<y.r;return x.cnt>y.cnt;}
};void solve(){int n,m,v,t;cin>>n>>m>>v>>t;vector<vector<pll>> e(n+1);for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e[u].push_back({v,w});e[v].push_back({u,w});}vi dis(n+1,inf);auto dij=[&](int s)->void{vb vis(n+1,false);priority_queue<node,vector<node>,cmp> q;q.push({1,s,v});dis[s]=1;while(!q.empty()){auto [cnt,x,r]=q.top();q.pop();if(vis[x]) continue;vis[x]=true;for(auto [y,w]:e[x]){int ct,re;if(w>r) {ct=cnt+1;re=v-w;}else {ct=cnt;re=r-w;}if(dis[y]>=ct){dis[y]=ct;q.push({ct,y,re});}}}};dij(t);for(int i=1;i<=n;i++){if(dis[i]>=inf) cout<<"-1 ";else cout<<dis[i]<<" ";}cout<<"\n";
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;// cin>>_;while(_--) solve();return 0;
}

A. Who Can Win

思路

纯模拟倒是没什么难度,对于每个队伍我们只需要维护两个值,一个是封榜后所有提交都没有通过,二是封榜后的提交都通过了,最后遍历一遍队伍看能否成为冠军即可

代码

#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;struct node{string na;char tm;int tim;string zt;
};
bool cmp(const node&a,const node&b){return a.tim<b.tim;
}
void solve(){int n;cin>>n;vector<node>a(n+1);for(int i=1;i<=n;i++){cin>>a[i].na>>a[i].tm>>a[i].tim>>a[i].zt;}sort(a.begin()+1,a.end(),cmp);map<string,set<char>>ac;map<string,int>fs;map<string,map<char,int>>mp;map<string,set<char>>mtg;map<string,int>mfs;for(int i=1;i<=n;i++){string name =a[i].na;char tm =a[i].tm;int time =a[i].tim;string res =a[i].zt;if(ac[name].count(tm))continue;if(res=="Accepted"){fs[name] += time;ac[name].insert(tm);}else if(res=="Rejected"){mp[name][tm]++;}else{if(mtg[name].count(tm))continue;mtg[name].insert(tm);mfs[name]+=time;mfs[name]+= mp[name][tm]*20;}}for(auto[x,y]:ac){for(auto ele:y){if(mp[x].count(ele)){fs[x]+=mp[x][ele]*20;}}}int fashi=1e18;int tg=0;for(auto[x,y]:ac){int cnt=y.size();if(tg==cnt){fashi=min(fashi,fs[x]);}else if(cnt>tg){tg=cnt;fashi=fs[x];}}vector<string>ans;for(auto[x,y]:ac){if(tg==y.size()&&fashi==fs[x]){ans.push_back(x);continue;}int add = mtg[x].size();if(add+y.size()>tg){ans.push_back(x);}else if(add+y.size()==tg){int tot =fs[x]+mfs[x];if(tot<=fashi){ans.push_back(x);}}}sort(ans.begin(),ans.end());for(auto s:ans){cout<<s<<' ';}cout<<endl;
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;cin>>_;while(_--) solve();return 0;
}

M. Teleporter

思路

用dp来做,dp[i][j]表示节点i在用j次捷径的情况下到达1所用的最短时间

那么对于dp[i][0]来说可以最初跑一遍bfs来初始化一下

对于dp[i][j]的更新,假设一条捷径为[x,y]那么可以得到明确的两个更新

dp[x][k]=min(dp[x][k],dp[y][k-1])

dp[y][k]=min(dp[y][k],dp[x][k-1])

但只需要更新这两个节点的dp值吗?并不是,我们仍需要跑dfs来更新其余节点的dp值,因为某节点可能在经由某个或多个捷径后到达节点1距离变短了

所以对于使用k次捷径,我们需要用dfs1从上到下,dfs2从下到上来更新所有节点的dp[][k]值

最终统计答案即可

代码

#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;void solve(){int n,m;cin>>n>>m;vector<vector<pll>> e(n+1);for(int i=1;i<n;i++){int u,v,w;cin>>u>>v>>w;e[u].push_back({v,w});e[v].push_back({u,w});}vector<pll> res(m+1);for(int i=1;i<=m;i++){cin>>res[i].first>>res[i].second;}vector<vi> dp(n+1,vi(n+1,inf));auto bfs=[&]()->void{dp[1][0]=0;queue<int> q;q.push(1);while(!q.empty()){int u=q.front();q.pop();for(auto [v,w]:e[u]){if(dp[v][0]!=inf) continue;dp[v][0]=dp[u][0]+w;q.push(v);}}};bfs();auto dfs1=[&](auto self,int u,int i,int fa)->void{for(auto [v,w]:e[u]){if(v==fa) continue;self(self,v,i,u);dp[u][i]=min(dp[u][i],dp[v][i]+w);}};auto dfs2=[&](auto self,int u,int i,int fa)->void{for(auto [v,w]:e[u]){if(v==fa) continue;dp[v][i]=min(dp[v][i],dp[u][i]+w);self(self,v,i,u);}};for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){auto [x,y]=res[j];dp[x][i]=min(dp[x][i],dp[y][i-1]);dp[y][i]=min(dp[y][i],dp[x][i-1]);}dfs1(dfs1,1,i,0);dfs2(dfs2,1,i,0);}//将dp[i][k]的意义变成不超过k次的最短距离for(int i=1;i<=n;i++){for(int k=1;k<=n;k++){dp[i][k]=min(dp[i][k],dp[i][k-1]);}}for(int k=0;k<=n;k++){int ans=0;for(int i=1;i<=n;i++){ans+=dp[i][k];}cout<<ans<<"\n";}
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;// cin>>_;while(_--) solve();return 0;
}

D. Min-Max Tree

思路

  1. 树形动态规划(DP):对于每个节点,我们维护三个状态:

    • dp[u][0]:表示以节点u为根的子树中,经过u的路径贡献之和的最大值。

    • dp[u][1]:表示以节点u为根的子树中,u作为路径最小值时的最大贡献。

    • dp[u][2]:表示以节点u为根的子树中,u作为路径最大值时的最大贡献。

  2. 状态转移:对于每个节点u,计算所有子节点v的dp[v][0]之和sum。然后计算updown

    • up:u作为最大值时,向下延伸路径的最大贡献,通过调整子节点v的贡献和权重差得到。

    • down:u作为最小值时,向下延伸路径的最大贡献,同样通过调整子节点v的贡献和权重差得到。

  3. 组合贡献:节点u作为中间点时,组合向上和向下的路径贡献,得到最终的总贡献。

代码

#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;void solve(){int n;cin>>n;vector<int> a(n+1);for(int i=1;i<=n;i++){cin>>a[i];}vector<vector<int>> e(n+1);for(int i=1;i<n;i++){int u,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}vector<array<int,3>> dp(n+1);auto dfs=[&](auto self,int u,int fa)->void{int sum=0;for(auto v:e[u]){if(v==fa) continue;self(self,v,u);sum+=dp[v][0];}int up=sum,down=sum;for(auto v:e[u]){if(v==fa) continue;up=max(up,sum-dp[v][0]+dp[v][2]+a[u]-a[v]);down=max(down,sum-dp[v][0]+dp[v][1]+a[v]-a[u]);}dp[u][0]=up+down-sum;dp[u][1]=down;dp[u][2]=up;};dfs(dfs,1,0);cout<<dp[1][0]<<"\n";
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;// cin>>_;while(_--) solve();return 0;
}

http://www.dtcms.com/a/391671.html

相关文章:

  • docker中ngnix的路径配置
  • 什么是黑板架构风格?
  • Redis 三大核心模式(主从复制 / 哨兵 / 集群):完整部署与问题解析
  • Docker生产环境容器OOM问题定位:镜像内存泄漏还是主机资源不足?
  • AcWing385. GF和猫咪的玩具——Floyd算法
  • 75、封装paddle ocr v5服务支持昇腾800 900 、800I A2、300I DUO卡推理识别
  • 【一文了解】线程的使用
  • 电力系统暂态稳定计算与单机无穷大系统建模
  • OmniGen2 - 智源研究院推出的开源多模态生成模型
  • 【故障排查:JDK8中Files.lines方法错误使用导致的Linux服务器文件描述符泄漏问题】
  • 【multisim仿真电子秒表74LS90】2022-12-15
  • v-show 和 v-if 的区别及使用场景
  • 动态二维码杜绝代签,手机端配置同步,巡检数据更可靠
  • 数据库学习MySQL系列6、MySQL入门简单练习使用
  • 交互式生成对抗网络(iGAN)
  • RecSys: 推荐系统重排与多样性优化(MMR以及DPP算法)
  • 瑞芯微MPP音视频框架---mjpeg解码
  • 模型部署:(七)安卓端部署OCR文本识别项目全流程记录
  • 用html5写一个超级计算器
  • 手机实现真随机数生成器
  • 119.计数器产生中断(上升沿)计算方法,比如cnt[21:0],那么assign time = cnt[20]这样大致是多长时间产生一次中断
  • VSCode c/c++头文件函数点击无法跳转问题
  • `mysql_real_connect` 函数全面深度解析
  • 深入解析Yum元数据安全与Artifactory自动化原理
  • 第三章 强化学习助力优化
  • 使用角色和Ansible内容集合简化Playbook
  • 鸿蒙应用集成Push Kit 指南
  • 树莓派ubuntu20.04实现ROS noetic与Arduino通信
  • 【代码随想录算法训练营——Day17】二叉树——654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
  • 托福听力44