首页 > 其他分享 >CF1249(Div. 3) 题解(A to D)

CF1249(Div. 3) 题解(A to D)

时间:2023-10-05 17:01:48浏览次数:32  
标签:cnt int 题解 线段 CF1249 cin ans Div

\(\texttt{E F}\) 忘(不)记(会)写了。

A Yet Another Dividing into Teams 题解

题目大意

有一个长度为 \(n\) 的序列 \(a_1,a_2,\cdots,a_n\),将他们分为若干组,使得每一组没有两个数的差为 \(1\),使分的组数尽可能少。

解题思路

排完序后对于任意 \(1\le i< n\) 均有 \(a_i\) 与 \(a_{i+1}\) 最接近,所以若存在 \(a_{i+1}-a_i=1\) 则必定要分成两组,否则一组。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
int a[N];
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);
  int t;
  cin >> t;
  while(t--) {
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++) {
      cin >> a[i];
    }
    int ans = 1;
    sort(a + 1, a + n + 1);
    for(int i = 2; i <= n; i++) {
      if(a[i - 1] + 1 == a[i]) {
        ans = 2;
        break;
      }
    }
    cout << ans << "\n";
  }
  return 0;
}

B1 & B2 Books Exchange 题解

题目大意

有 \(n\) 个小朋友每人手里有一本书,给定一个排列 \(a\),表示每一轮第 \(i\) 个小朋友会把书给 \(a_i\)。求每个小朋友的书会在几轮后回到自己手里。

解题思路

暴搜寻找即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 205;
int t, n, a[N];
inline int dfs(int cur, int x, int y) {
  if(y == x && cur != 0) {
    return cur;
  }
  return dfs(cur + 1, a[x], y);
}
int main() {
  ios::sync_woth_stdio(0);
  cin.tie(0), cout.tie(0);
  int t;
  cin >> t;
  while(t--) {
    cin >> n;
    for(int i = 1; i <= n; i++) {
      cin >> a[i];
    }
    for(int i = 1; i <= n; i++) {
      cout << dfs(0, i, i) << " ";
    }
    cout << "\n";
  }
  return 0;
}

C1 & C2 Good Numbers 题解

题目大意

给定 \(n\),求不小于 \(n\) 的最小数 \(x\),使得 \(x\) 可以分解成不同的 \(3\) 的幂之和。其中 \(C2\) 的数据规模更大。

解题思路

我们只需要算出 \(3^i\) 的前缀和 \(s_i\),然后从大到小判断是否要选 \(3^i\) 作为 \(x\) 的一部分,如果 已选数字之和加上 \(s_{i-1}\le x\) 那么说明当前 \(3^i\) 不用选。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 1e18;
int n, ans, sum[105], a[105];
inline int solve(long long x) {
  int ans = 0;
  for(int i = 38; i >= 1; i--) {
    if(ans + sum[i - 1] >= x) {
      continue;
    } else {
      ans += a[i];
    }
  }
  if(ans < x) {
    ans += 1;
  }
  return ans;
}
signed main() {
  sum[0] = 1;
  a[0] = 1;
  long long cnt = 3;
  for(int i = 1; i <= 100 && sum[i - 1] <= INF; i++) {
    sum[i] = sum[i - 1] + cnt;
    a[i] = cnt;
    cnt *= 3;
  }
  int t;
  cin >> t;
  while(t--) {
    cin >> n;
    cout << solve(n) << "\n";
  }
  return 0;
}

D1 & D2 Too Many Segments 题解

题目大意

给定 \(n\) 个区间,要求删除最少数量的区间,使得每个点被覆盖的次数不超过 \(k\),求方案。

解题思路

我们首先要做的事情就是能够计算出当前点 \(x\) 处被几条线段覆盖的问题。我们需要先将所有线段按左端点排序,用差分维护线段结束,然后枚举每条线段,每枚举一个线段我们就让 \(cnt+1\), 表示当前点 a[i].l 有 \(cnt\) 个线段覆盖,同时 sum[a[i].r]--,表示线段在 a[i].r 在这里结束。当我们在判断当前点 a[i].l 被几条线段覆盖时,还需要去掉右端点已经小于 a[i].l 的线段,这样就得到了当前点 a[i].l 有 \(cnt\) 个线段覆盖。然后判断 \(cnt>k\),如果 \(cnt>k\) 说明需要去掉线段,我们优先去掉右端点最大的线段。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, k;
int sum[N], cnt, pos;
vector<int> ans;
priority_queue<pair<int, int> > p;
struct node {
  int l, r, id;
} a[N];
inline bool cmp(node x, node y) {
  if(x.l == y.l) {
    return x.r > y.r;
  }
  return x.l < y.l;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);
  cin >> n >> k;
  for(int i = 1; i <= n; i++) {
    cin >> a[i].l >> a[i].r;
    a[i].id = i;
  }
  sort(a + 1, a + 1 + n, cmp);
  for(int i = 1; i <= n; i++) {
    p.push(make_pair(a[i].r, a[i].id));
    cnt++;
    sum[a[i].r]--;
    while(pos < a[i].l) {
      cnt = cnt + sum[pos];
      pos++;
    }
    if(a[i].l != a[i + 1].l) {
      while(cnt > k) {
        while(!p.empty() && p.top().first < a[i].l) {
          p.pop();
        }
        ans.push_back(p.top().second);
        sum[p.top().first]++;
        p.pop();
        cnt--;
      }
    }
  }
  cout << ans.size() << "\n";
  for(int i = 0; i < ans.size(); i++) {
    cout << ans[i] << " ";
  }
  cout << "\n";
  return 0;
}

标签:cnt,int,题解,线段,CF1249,cin,ans,Div
From: https://www.cnblogs.com/cyf1208/p/17743546.html

相关文章

  • Luogu CF1174C 题解
    这道题其实不难。\(\gcd(i,j)=1\),其实就是\(i\)与\(j\)互质。如果\(i\)与\(j\)不互质,那么我们一定要让\(a_i\)与\(a_j\)相同,只有这样,才能使\(a\)序列中的最大值最小化。所以,我们可以使用埃氏筛法,当筛到质数时,给它和它的倍数都赋值为一个新数。ACCode:#include......
  • Luogu P8651 题解
    这是让我最崩溃的一道橙题了。整整11次提交才AC。这道题有几个要点必须注意:判断日期是否合理。按顺序输出。判断重复的日期。首先,我们来看怎么判断日期是否合理。我们知道大月有\(31\)天,小月有\(30\)天,二月看平年闰年。所以,我们可以写出这样的代码:boolc......
  • Luogu CF1469B 题解
    这道题其实并不难。题目大意是这样的:已知两个序列\(r\)和\(b\),求出合并后的最大前缀和。很好发现:答案就是\(r\)和\(b\)各自的最大前缀和之和。但要注意:\(r\)和\(b\)可以什么都不取,因此\(maxa\)和\(maxb\)初始要赋值为\(0\)。ACCode:#include<iostream>using......
  • Luogu CF755B 题解
    这题其实不难。两人最佳的方案就是先说对方会的词。不难证明,设先手会说\(n\)个单词,后手会说\(m\)个单词,若\(n>m\),则先手胜,若\(n<m\),则后手胜。那如果\(n=m\)呢?假设两人都会说的单词数为\(k\),那么一番推理发现,当两人说了\(k-1\)次,就没有两人都会的词了,可以回到之......
  • Luogu CF1133B 题解
    这道题其实很简单要让两数和为\(k\)的倍数,需要满足以下两条件之一:两数都是\(k\)的倍数两数的余数和为\(k\)因此,我们可以先统计出余数再按上述条件算出共有多少组,即可得到答案注意:当\(k\)为偶数时,余数为\(k/2\)的数要两两配对,不要多算这里统计的是组数,......
  • Luogu P7627 题解
    这题其实不难但如果用暴力,肯定过不了所以我们得想另一种办法我们发现,只有\(1\)异或\(0\)的值为\(1\)例如:\(1\),\(0\),\(1\)两两异或的和为2其实就是每个\(0\)与每一个\(1\)异或时,\(sum\)要加\(1\)所以,我们只要把每一位的\(0\)和\(1\)的数量都统计出来......
  • Luogu CF400C 题解
    这道题其实不难,只是一道非常简单的模拟题。我们发现,每顺时针转动\(4\)次、镜面对称\(2\)次、逆时针旋转\(4\)次,就变回原来的样子了。所以,在操作前,我们可以让\(x\getsx\bmod4\),\(y\getsy\bmod2\),\(z\getsz\bmod4\)。接下来,只需在草稿纸上画一画,即可知道顺时针转一次,一......
  • CodeForces 814E An unavoidable detour for home 题解
    更好的阅读体验题意题目链接(洛谷翻译)给出\(n\)个点,和每个点的度\(d_i\)让你构造出一张无向图满足以下两条性质:点\(1\)到点\(i\)仅有唯一一条最短路。点\(1\)到点\(i\)的最短路长度大于等于点\(1\)到点\(i-1\)的最短路长度。求能构成满足条件的无向图......
  • [题解] CF474E Pillars
    题意给定长度为\(n\)的序列\(a\)和常数\(d\),输出一个最长的\(a\)的子序列,使得相邻两项的差的绝对值大于等于\(d\)。\(n\le10^5\)题解数据结构优化DP的板子题了吧。首先,这道题看上去就很LIS,我们尝试着用类似LIS的思路去做。设\(f_i\)表示以\(i\)结尾的符合......
  • 题解 accoders::NOI 5510【飞翔的胖鸟(fly)】
    题解accoders::NOI5510【飞翔的胖鸟(fly)】problem求\(f(x)=\frac{ah}{\sin(x)}+bx\)在\((0,\frac\pi2]\)上的最小值。solution\(\sin'(x)=cos(x);\cos'(x)=-\sin(x)\)。\((f(x)\cdotg(x))'=f'(x)g(x)+f(x)g'(x)\)。\(\left(\dfrac{f......