首页 > 其他分享 >Codeforces 1852A Ntarsis' Set 题解

Codeforces 1852A Ntarsis' Set 题解

时间:2023-07-25 21:25:00浏览次数:44  
标签:Ntarsis Set 题解 元素 贡献 插入 ans inc

题目传送门:Codeforces 1852A Ntarsis' Set

题意

给定一个集合,里面初始有 \(1,2,3...10^{1000}\),告诉你每天会拿掉其中的第 \(a_1, a_2, a_3 ...a_n\) 个,询问这样的 \(k\) 天之后剩下的最小的数是多少。

分析

  • 思考如果 \(x\) 在这天没有被删掉,那么哪些被删掉的位置会对它产生什么样的影响

    解答:如果 \(a_i < pos_{x} < a_{i + 1}\) ,那么他会移动到 \(pos_x - i\) 的位置

  • 带着这个发现,去反向模拟

题解

首先我们运用逆向思维,不去直接模拟删除元素,而是模拟插入 \(0\) 的过程,其中每一轮将 \(0\) 插入要删除的位置,即 $ a_i - i$ ,这样操作 \(k\) 天后,1出现的位置即为输出结果。

如何模拟这个过程呢?我们可以简化这个思路,第一个 \(1\) 之后插入的 \(0\) 是对答案没有贡献的,因此我们只需要计算哪些插入对答案有贡献即可,如何计算数值在第几天之后有贡献呢:

  • 如果第一个元素是 \(1\) ,那么第一天就会有贡献
  • 如果第二个元素是 \(2\) ,那么第二天会有贡献
  • 如果第二个元素是 \(4\) ,那么第四天会有贡献
  • 推广至第 \(inc\) 个元素,设当前 \(1\) 的位置为 \(ans\) ,那么还需要(a[inc] - ans + inc - 1) / inc 天才能有贡献

AC代码

#include <bits/stdc++.h>
using namespace std;

int n, k, a[200010];

void solve() {
    cin >> n >> k;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] -= i;
    }
    if (a[0] != 1) {
        cout << 1 << "\n";
        return;
    }
    a[n] = 2e9;
    //start at position 1, and find what number moves to its position
    long long ans = 1;
    int inc = 1; //how many zeroes to insert
    while (inc < n) {
        int days = (a[inc] - ans + inc - 1) / inc; // 需要多少天才能有效贡献
        if (days >= k){ // k不足,计算之前的元素可以贡献的有效的插入的0
            ans += k * inc;
            k = 0;
            break;
        }
        ans += days * inc; // k充足,计算总贡献
        k -= days; // 这里 - days,表示 花费的轮数
        // 小于的元素,表示已经被前面的其他元素覆盖,没起作用
        while (a[inc] <= ans) inc++; 
    }
    ans += 1ll * k * n; // 剩下的k轮,每次可以插入n个0,走n步
    cout << ans << "\n";
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(nullptr);

    int t; cin >> t;
    while (t--) solve();
}

标签:Ntarsis,Set,题解,元素,贡献,插入,ans,inc
From: https://www.cnblogs.com/marti88414/p/17581045.html

相关文章

  • CF1776M Parmigiana With Seafood 题解
    先将所有的叶子取\(\max\)贡献给答案,以下讨论的所有点中不考虑叶子。首先可以考虑先手能否删到\(n\):不难发现当\(2\midn\)的时候可以,然后我们就排除了一半的\(n\),于是以下令\(2\not\midn\)。接下来,考虑先手能否删掉\(n-1\),那么把\(n-1\ton\)的路径当成一个大点,......
  • 聊聊List、Set、Map
    1.List哪些实现类JavaList一共三个实现类分别是ArrayList、Vector和LinkedList。(1)ArrayList是最常见用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已有数组的数据复制到......
  • 洛谷 P9221 「TAOI-1」Pentiment 题解
    Description给定\(n\timesm\)的矩阵,从第\(1\)行任意格子出发,每次向下、左、有走一步,有\(q\)个障碍不能经过,求走到第\(n\)行任意格子的方案。对于所有数据,\(1\leqn,m\leq10^9\),\(1\leqq\leq10^5\)。link:https://www.luogu.com.cn/problem/P9221Solution算法一考......
  • 题解 LGP2300【合并神犇】
    Problem随机\(n\)个正整数组成序列。将序列分尽量多的段数,使得前一段的和不大于后一段的和。求能分成多少段。输出\(n-ans\)。\(n\leq10^5\),值域不重要。Solution状态设计为:\(f_i=1+\min_{sum_i-sum_j\geqg_j}f_j\)表示前\(i\)个数字划分的最多段数,\(g_j\)定义为\(f_......
  • 洛谷P3629 [APIO2010] 巡逻题解
    题目链接P3629[APIO2010]巡逻-洛谷|计算机科学教育新生态(luogu.com.cn)思路n个村庄,n-1条道路,原图为树1.若k=0(不修建道路)那么答案为(n-1)*2 每个道路会走两遍2.若k为1(修建一条道路)设修建的道路(r1)所在的环长度为L那么答案为(n-1)*2-L+2可以看到r1所在环的道路只走了......
  • 题解 P1150 【Peter的烟】
    postedon2020-11-1410:00:20|under题解|source2023编者注:本篇题解的方法过于暴力,但是尊重历史。请不要太在意。—-教你们用栈做这道题原题传送门看到这题,第一反应是用stack做。我们可以把Peter手上的烟看作一个栈,一根烟就是一个元素,抽了\(n\)支烟就从栈里pop几个,......
  • 题解 P1008 【三连击】
    postedon2020-11-1217:25:10|under题解|source2023编者注:请尊重历史。本题正解是暴力枚举先引用我们老师的一句话:(无恶意)不会吧不会吧,不会还有人不会写三连击吧!废话不多说,开始解题:理解题目和做题思路P1008三连击题目链接:https://www.luogu.com.cn/problem/......
  • 题解 CF1501A 【Alexey and Train】
    postedon2021-03-1321:57:02|under题解|source简单模拟题,考验选手的读题能力和使用谷歌翻译的能力。先定义一个\(now=0\),我们最后算出来的结果为\(now\)。对于每个站(不包括第\(n\)站),我们需要加上\(3\)个部分:额外时间,now+=ex[i];第\(i-1\)站到第\(i\)站的时......
  • 题解 CF1501B 【Napoleon Cake】
    postedon2021-03-1617:42:06|under题解|source题目可以转化一下:给一个长为\(n\)的数组\(a\),请求出一个长为\(n\)的数组\(b\)。要求若\(a_i\)不为\(0\),则\([b_{i-a_i+1},b_i]\)这个区间要为\(1\)。知道这个题目意思就好办了。题目说\(n\leq2\times10^5\),......
  • 题解 CF1497C2 【k-LCM (hard version)】
    postedon2021-03-2009:09:40|under题解|source2023编者注:有一些链接点不进去,分别是cf1497c1的cf页面和https://www.cnblogs.com/caijianhong/p/Solution-cf1497c1.html此题与CF1497C1有异曲同工之妙。我们知道,\(\operatorname{lcm}(1,x)=x\),不难想到,\(\operato......