8.9套题

打印 上一主题 下一主题

主题 993|帖子 993|积分 2979

A. 猴猴吃苹果

题意:给定根节点k,求访问点的顺序,使得每次从上一个点到当前点的权值最大。访问过的点权值为0。权值一样时,输出最小编号
思绪:由于是双向边,先求根节点到每一个节点的间隔值。在第一轮中,最深的叶节点一定为答案,那么这一条路径就被访问过了,权值变为0,这个叶节点相同路径上的其他点到根节点(末了一个未被标记的点)的权值就改变了。所以从最优的叶节点出发,dfs往上跳,直到访问到已经被访问过的点为止即可。末了排序更新后的权值
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e6 + 10;
  4. int n,k,d[N],tot;
  5. bool vis[N];
  6. struct node{
  7.         int id,val;
  8. }a[N];
  9. vector<int> v[N];
  10. inline bool cmp(node p,node q){
  11.         if(p.val!=q.val)  return p.val>q.val;
  12.         else return p.id<q.id;
  13. }
  14. void dfs1(int p,int fa){
  15.         for(int t:v[p]){
  16.                 if(t==fa)  continue;
  17.                 d[t]=d[p]+1;
  18.                 dfs1(t,p);
  19.         }
  20. }
  21. void dfs2(int p,int fa){
  22.         if(vis[p])  return;
  23.         tot++;
  24.         vis[p]=true;
  25.         for(int t:v[p]){
  26.                 if(t==fa||d[t]>=d[p])  continue;
  27.                 dfs2(t,p);
  28.         }
  29. }
  30. int main(){
  31.         cin>>n>>k;
  32.         for(int i=1,x;i<n;i++){
  33.                 cin>>x;
  34.                 v[i].push_back(x);
  35.                 v[x].push_back(i);
  36.         }
  37.     dfs1(k,-1);vis[k]=true;
  38.     for(int i=0;i<n;i++){
  39.             a[i].id=i;a[i].val=d[i];
  40.         }
  41.         sort(a,a+n,cmp);
  42. //        for(int i=0;i<n;i++)  cout<<a[i].id<<" ";
  43.     for(int i=0;i<n;i++){
  44.             tot=0;
  45.             dfs2(a[i].id,-1);
  46.             a[i].val=tot;
  47. //            cout<<tot<<" "<<a[i].id<<endl;
  48.         }
  49.         sort(a,a+n,cmp);
  50.         cout<<k<<endl;
  51.         for(int i=0;i<n;i++){
  52.                 if(a[i].val)
  53.                   cout<<a[i].id<<endl;
  54.         }
  55.         return 0;
  56. }
复制代码
B. 猴猴吃香蕉

题意:选取n个数中的若干个数,使得它们的乘积为k
思绪:计数dp,容易得出
的转移方程式。使得
为构成k的一个因子。由于k的范围不可接受,于是筛出k的所有因子,如果
能整除,说明这个数能被分解。
,由于因子较大,且个数趋近根号n,必要离散化
终极dp方程:
,答案为

C. 猴猴的比赛

题意:给定两棵树,求一个节点x在两棵树中有相同祖先的对数
思绪:考虑求出每一个点的子树中的范围
(一连的),对于另一颗树而言,每次处理一个点答案计数完成后,就将这个点在第一棵树中的位置标记为1。答案计数为所有父节点
中1的数量。注意在遍历子节点时,必要减去子树所有点的
中1的数量,防止重复运算
焦点代码:
  1. void dfs2(int p,int fa){
  2.         //L[p]为点p的dfn序
  3.         for(int t:g[p]){
  4.                 if(t==fa)  continue;
  5.                 ans-=BIT.query(R[t])-BIT.query(L[t]);
  6.                 dfs2(t,p);
  7.         }
  8.         ans+=BIT.query(R[p])-BIT.query(L[p]);//整个子树
  9.         BIT.add(L[p],1);
  10. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美丽的神话

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表