Codeforces Round 867 (Div. 3)

文章讨论了如何在树形结构中计算每个节点到最远节点的距离,并基于此解决最大收益问题。通过两次深度优先搜索维护每个节点的最远距离和深度信息,然后计算以每个节点为根的最大收益。此外,还涉及到了一个关于数的计数问题,对于不同规模的数据集有不同的解法策略,如简单的遍历和因数分解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

掉分md

D: 数学构造

E : 简单思维

F:图论,树 ,树的中心,维护对于树上每个点,到该点的最远距离是多少,板子

G:数学,计数

F:

题意:题意:树的收益是root(初始root=1)到最远的点的距离,更改相邻一个点成为root的要付出代价是c。    求最大利润

分析:只需维护出树上每个点与 距离最远的点的距离是多少。参考acwing树的中心,以及前不久div2 的一个D题也是这么做。

每个点当做root的收益 就是最远的点到自己的距离,减去成为根节点的代价(深度-1)  取最大值即可。

板子:求对于树上每一个点,最远的点到自己的距离是多少  max(d1[i],up[i])

  1. //dfs1
  2. //dfs2
  3. //维护出每一个点的深度
  4. //维护出每一个点到最远的点的距离
  5. //树的中心
  6. int deg[N]; //深度
  7. int d1[N],d2[N],p1[N],p2[N],up[N];
  8. void dfs1(int u,int fa)
  9. {
  10.     deg[u]=deg[fa]+1;
  11.     for(int i=h[u];i!=-1;i=ne[i])
  12.     {
  13.         int j=e[i];
  14.         if(j==fa)
  15.             continue;
  16.         dfs1(j,u);
  17.         if(1+d1[j]>=d1[u])
  18.         {
  19.             d2[u]=d1[u];
  20.             p2[u]=p1[u];
  21.             d1[u]=1+d1[j];
  22.             p1[u]=j;
  23.         }
  24.         else if(1+d1[j]>d2[u])
  25.         {
  26.             d2[u]=1+d1[j];
  27.             p2[u]=j;
  28.         }
  29.     }
  30. }
  31. void dfs2(int u,int fa)
  32. {
  33.     for(int i=h[u];i!=-1;i=ne[i])
  34.     {
  35.         int j=e[i];
  36.         if(j==fa)
  37.             continue;
  38.         if(p1[u]==j)
  39.             up[j]=1+max(up[u],d2[u]);
  40.         else
  41.             up[j]=1+max(up[u],d1[u]);
  42.         dfs2(j,u);
  43.     }
  44. }

  1. //dfs求代价
  2.     dfs1(1,0);
  3.     dfs2(1,0);
  4.     ll res=0;
  5.     for(int i=1;i<=n;i++)   //枚举这个点成为root的收益
  6.         res=max(res, (ll)k*max(up[i],d1[i])-((ll)deg[i]-1)*c );
  7.     cout<<res<<endl;

G

简单版本 G1 ai<=1e6

困难版本 G2 ai<=1e9

问有多少个三元组( i,j,k ) (允许相等)满足 存在b ,使得a[j]=a[i]*b, a[k]=a[j]*b

Easy verson:

遍历i, 遍历b 。直接计数 cnt[a[i]] *cnt[a[i]*b]*cnt[a[i]*b*b]即可

用数组计数,每次清空。 同时离散化去重应该会快一些

  1. sort(a.begin(),a.end());
  2.     a.erase(unique(a.begin(),a.end()) ,a.end());
  3.     int ma=a.back();
  4.     for(int i=0;i<a.size();i++)
  5.     {
  6.         if(cnt[a[i]]>=3)
  7.             res+=(ll)(cnt[a[i]])*(cnt[a[i]]-1)*(cnt[a[i]]-2);
  8.         for(int j=2;;j++)   //倍数
  9.         {
  10.             ll t1=(ll)a[i]*j;
  11.             ll t2=(ll)(a[i])*j*j;
  12.             if(t2>ma||t1>ma)
  13.                 break;
  14.             else if(cnt[t1]!=0&&cnt[t2]!=0)
  15.                 res+=(ll)cnt[a[i]]*cnt[t1]*cnt[t2];
  16.         }
  17.     }
  18.     cout<<res<<endl;
  19.     for(int i=0;i<a.size();i++)
  20.         cnt[a[i]]=0;
  21.     //清空
  22. }

竟然卡map, unordered_map能过。

G2  

困难版本: 区别,a[i]<=1e9,

统计 存在b,使得 a[i]*b=a[j],a[j]*b=a[k], 三元组( I,j,k)的个数

对于a[i]>=1e6的数, 枚举中间的数a[j],以及枚举b, 因为a[k]<=1e9;

所以b最多枚举1000

对于a[i]<=1e6的数,若固定a[i]或者固定a[j]枚举b的话,b的量级==(1e9)/a[i],量级可达很高,时间复杂度不可接受  这时可枚举a[j]的因子,因数分解的时间复杂度为根号a[i],时间复杂度为1000.可接受  总的复杂度为 n* 1000差不多

强调:longlong 的运算速度比int要慢,这题对时间卡的很极限,longlong大概率T掉

代码:服了,T49,再想想

  1.     //枚举中间数a[j]  //计数a[j]/b,a[j],a[j]*b;
  2.     //计数
  3.     int ma=a.back();
  4.     for(int i=0;i<a.size();i++)
  5.     {
  6.         if(mp[a[i]]>=3)
  7.             res+=(ll)mp[a[i]]*(mp[a[i]]-1)*(mp[a[i]]-2);
  8.         if(a[i]==1)
  9.             continue;
  10.        
  11.         if(a[i]<=1e6)
  12.         {
  13.             //质因数分解
  14.             //枚举它的所有因数
  15.             for(int j=1;j<=a[i]/j;j++)
  16.             {
  17.                 if(a[i]%j==0)
  18.                 {
  19.                     if((ll)a[i]/j*a[i]<=ma)
  20.                         res+= (ll)mp[j]*mp[a[i]]*mp[a[i]/j*a[i]];
  21.      
  22.                     if(j!=1&&a[i]/j!=j)
  23.                     {
  24.                         int j1=a[i]/j;
  25.                         if((ll)a[i]/j1*a[i]<=ma)
  26.                         res+= (ll)mp[j1]*mp[a[i]]*mp[a[i]/j1*a[i]];
  27.                     }
  28.                 }
  29.             }
  30.         }
  31.         else
  32.         {
  33.             for(int b=2;b<=ma/a[i];b++)
  34.             {
  35.                 if(a[i]%b!=0)
  36.                     continue;
  37.                 if((ll)a[i]*b<=ma)
  38.                 res+= (ll)mp[a[i]/b ]*mp[a[i]]*mp[a[i]*b ];
  39.             }
  40.         }
  41.     }
  42.     cout<<res<<endl;
  43. }
### Codeforces Round 927 Div. 3 比赛详情 Codeforces是一个面向全球程序员的比赛平台,定期举办不同级别的编程竞赛。Div. 3系列比赛专为评级较低的选手设计,旨在提供更简单的问题让新手能够参与并提升技能[^1]。 #### 参赛规则概述 这类赛事通常允许单人参加,在规定时间内解决尽可能多的问题来获得分数。评分机制基于解决问题的速度以及提交答案的成功率。比赛中可能会有预测试案例用于即时反馈,而最终得分取决于系统测试的结果。此外,还存在反作弊措施以确保公平竞争环境。 ### 题目解析:Moving Platforms (G) 在这道题中,给定一系列移动平台的位置和速度向量,询问某时刻这些平台是否会形成一条连续路径使得可以从最左端到达最右端。此问题涉及到几何学中的线段交集判断和平面直角坐标系内的相对运动分析。 为了处理这个问题,可以采用如下方法: - **输入数据结构化**:读取所有平台的数据,并将其存储在一个合适的数据结构里以便后续操作。 - **时间轴离散化**:考虑到浮点数精度误差可能导致计算错误,应该把整个过程划分成若干个小的时间间隔来进行模拟仿真。 - **碰撞检测算法实现**:编写函数用来判定任意两个矩形之间是否存在重叠区域;当发现新的连接关系时更新可达性矩阵。 - **连通分量查找技术应用**:利用图论知识快速求解当前状态下哪些节点属于同一个集合内——即能否通过其他成员间接相连。 最后输出结果前记得考虑边界条件! ```cpp // 假设已经定义好了必要的类和辅助功能... bool canReachEnd(vector<Platform>& platforms, double endTime){ // 初始化工作... for(double currentTime = startTime; currentTime <= endTime ;currentTime += deltaT){ updatePositions(platforms, currentTime); buildAdjacencyMatrix(platforms); if(isConnected(startNode,endNode)){ return true; } } return false; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值