Codeforces Round 1000 (Div. 2)(前三题)

A. Minimal Coprime

翻译:

        如果 l 和 r 互为同素数,则正整数 [l,r] 的一段称为同素段。

        如果一个共素数段 [l,r] 不包含任何不等于它本身的共素数段,那么这个共素数段 [l,r] 就叫做最小共素数段。为了更好地理解这句话,可以参考注释。

        给定正整数段 [l,r],求 [l,r] 中包含的最小共素数段的个数。

思路:

题目要求不同整数段之间不能为包含关系。

对于一个整数x与x+1必定为互素。

因此答案为r-l+1(l与r都不为1)

实现:

#include
using namespace std;
using ll = long long;
// using pll = pair;

void solve(){
  int a,b;
  cin>>a>>b;
  int ans = 0;
  if (a==1&&b==1){
    cout<<1<>t;
    while (t--) solve();
}

B. Subsequence Update

 翻译:

        给你一个整数序列 a_{1},a_{2},...,a_{n},和一个线段 [l,r](1≤l≤r≤n)。

        你必须对这个序列执行下面的操作一次。

  • 选择序列 a 的任意子序列,并反转它。注意,子序列不一定要连续。

        形式上,选择任意数量的下标i_{1},i_{2},...,i_{k},使得 1\leq i_{1}\leq i_{2}\leq ... \leq i_{k}\leq n。然后,将所有 1≤x≤k 的第 i_{x}个元素同时改为第 i_{k-x+1}个元素的原始值。

求操作后 a_{l}+a_{l+1}+...+a_{r-1}+a_{r} 的最小值。

思路:

对于这只能一次的反转,可以选择要求段的左边的小值与要求段的大值交换。或要求段的右边的小值与要求段的大值交换。注意只能选一边,因为只能反转一次。

实现:

#include
using namespace std;
using ll = long long;
// using pll = pair;

void solve(){
  int n,l,r;
  cin>>n>>l>>r;
  ll res = 0;
  vector a(n+1);
  for (int i=1;i<=n;i++) cin>>a[i];
  priority_queue tmpl_ans,tmpr_ans;
  priority_queue,greater> lans,rans; 
  for (int i=l;i<=r;i++){
    res += a[i];
    tmpl_ans.push(a[i]);
    tmpr_ans.push(a[i]);
  } 
  for (int i=1;inow2){
      res -= now1-now2;
      tmpl_ans.pop();
      tmpl_ans.push(now2);
      lans.pop();
    }else{
      break;
    }
  }
  while (!rans.empty()){
    int now1 = tmpr_ans.top(),now2 = rans.top();
    if (now1>now2){
      res1 -= now1-now2;
      tmpr_ans.pop();
      tmpr_ans.push(now2);
      rans.pop();
    }else{
      break;
    }
  }
  cout<>t;
    while (t--) solve();
}

C. Remove Exactly Two

 翻译:

        给您一棵有 n 个顶点的树。您必须准确执行以下操作两次。

  • 选择一个顶点 v;
  • 删除 v 所带的所有边,同时删除顶点 v。

        请找出精确执行两次操作后的最大连通部分数。

        当且仅当存在一条从 x 到 y 的路径时,两个顶点 x 和 y 位于同一个连通组件中。
 根据定义,0 个顶点的图有 0 个连通成分。

思路:

记录每个点的度数,并从度数大层数的开始遍历。

那么答案有两种情况:

  1. 点a的度数+点b的度数-1      a与b不相连
  2. 点a的度数+点b的度数-2      a与b相连

实现:

#include
using namespace std;
using ll = long long;

void solve(){
  int n;    
  cin>>n;
  // 记录每个点的度数
  vector dus(n+1,0);
  // 创建邻接表
  vector> edge(n+1);
  for (int a,b,i=1;i>a>>b;
    dus[a]++;
    dus[b]++;
    edge[a].push_back(b);
    edge[b].push_back(a);
  }
  // 记录每个度数所包含的点
  map> mp;
  for (int i=1;i<=n;i++) mp[dus[i]].push_back(i);
  
  // 考虑到有的度数只有一个点增加记录点
  int f=0,f_du = 0;
  // 按度数从大到小遍历
  for (auto iter=mp.rbegin();iter!=mp.rend();iter++){
    int du = iter->first;
    auto nums = iter->second;
    int num_size = nums.size();
    if (f){
      for (int i:nums){
        // 两个点不相连
        if (find(edge[i].begin(),edge[i].end(),f)==edge[i].end()){
          cout<>t;
    while (t--) solve();
}

                                                                                              有建议可以评论,我会积极改进qwq。

你可能感兴趣的:(#,codeforces周赛,c++,算法,数据结构)