Codeforces Round #615 (Div. 3). D - MEX maximizing

题面:https://codeforces.com/contest/1294/problem/D

题目大意:

每次都会往你的数列里加一个值,你可以任意加减这个值若干次(但是只能加x或者减x)

然后问最小的不属于这个数列的非负整数是什么

你需要进行的操作是,让这个最小的不属于这个数列的非负整数最大

每次加一个值并且询问一遍

解题思路:

易得到,每一次输出的答案在进行完题目的贪心后会呈现上升趋势,且值最大只可能为序列内元素的个数

所以我们可以让每次加入的值在进行完若干次操作后尽量成为靠前的序列中还没出现过的数值,以助于答案能尽量变得更大

举题目的样例,不能按照Hint的思想去想,根据上述思想可以得到下面的步骤——

q=7,x=3

加入0,序列为[0],答案为1

加入1,序列为[0,1],答案为2

加入2,序列为[0,1,2],答案为3

加入2,因为2存在过,所以贪心让2变成尽量靠前的未出现的数,即5,所以序列为[0,1,2,5],答案为3

加入0,因为0存在过,所以贪心让0变成尽量靠前的未出现的数,即3,序列为[0,1,2,3,5],答案为4

加入0,因为0存在过,贪心让0变成尽量靠前的未出现的数,又因为3也出现过,所以为6,序列为[0,1,2,3,5,6],答案为4

加入10,10未出现过,变成尽量靠前的未出现的数,可得能够变成4,序列为[0,1,2,3,4,5,6],答案为7

经过以上操作,可以发现一个规律

不管怎么让新加进来的值d怎么变(+x/-x),d%x的值保持不变

所以可以想到用一个数组mini存不同的d%x这一类数字此时最小的未出现过的值

其后每次加进来一个值d,取mini[d%x]让这个数加进当前的序列内,然后让mini[d%x]+x成为下一个未出现过的数即可

如果mini[t]>q了,说明这一类的数字太多了,再加对答案也不会有贡献,就可以不考虑了

然后让答案作为一个变量,因为答案只增不减,每次就保持它的状态即可,在可以尝试增大时用

while(arr[ans])ans++;

来让他增大即可(arr数组判断数是否存在于序列内)

 1 /*
 2 Written By StelaYuri
 3 On 2020/01/22
 4 */
 5 #include<bits/stdc++.h>
 6 using namespace std;
 7 bool arr[400050];//判断i是否存在于当前的数列内
 8 int mini[400050];//d%x的种类之下未出现在arr序列中的最小数
 9 void solve(){
10     int q,x,d,t,i,ans=0;
11     cin>>q>>x;
12     for(i=0;i<x;i++)
13         mini[i]=i;
14     for(i=0;i<q;i++){
15         cin>>d;
16         t=d%x;
17         if(mini[t]<=q){
18             arr[mini[t]]=true;
19             while(arr[ans])
20                 ans++;
21             mini[t]+=x;
22         }
23         cout<<ans<<‘\n‘;
24     }
25 }
26 int main(){
27     ios::sync_with_stdio(0);
28     cin.tie(0);cout.tie(0);
29     solve();
30
31     return 0;
32 }

或者简化下代码,意思不变,此时只要多进行取模运算即可

 1 /*
 2 Written By StelaYuri
 3 On 2020/01/22
 4 */
 5 #include<bits/stdc++.h>
 6 using namespace std;
 7 int arr[400050];
 8 void solve(){
 9     int q,x,d,t,i,ans=0;
10     cin>>q>>x;
11     while(q--){
12         cin>>d;
13         arr[d%x]++;
14         while(arr[ans%x]){
15             arr[ans%x]--;
16             ans++;
17         }
18         cout<<ans<<‘\n‘;
19     }
20 }
21 int main(){
22     ios::sync_with_stdio(0);
23     cin.tie(0);cout.tie(0);
24     solve();
25
26     return 0;
27 }

原文地址:https://www.cnblogs.com/stelayuri/p/12230033.html

时间: 2024-10-11 07:41:13

Codeforces Round #615 (Div. 3). D - MEX maximizing的相关文章

Codeforces Round #615 (Div. 3) A-F简要题解

contest链接:https://codeforces.com/contest/1294 A. 给出a.b.c三个数,从n中分配给a.b.c,问能否使得a = b = c.计算a,b,c三个数的差值之和,n对其取余,判断是否为0即可. AC代码: 1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring>

Codeforces Round #615 (Div. 3)

暂时没有F题的题解.太菜了. A - Collecting Coins 题意:有三个人,分别有a,b,c枚硬币,你有n枚硬币,要求把n枚硬币全部给这三个人并且使得他们的硬币数变为相等.问是否可行. 题解:先验证硬币总数a+b+c+n是否能被3整除,然后验证要补的硬币的数量少于n. void test_case() { int a[5], n; scanf("%d%d%d%d", &a[1], &a[2], &a[3], &n); sort(a + 1,

Codeforces Round #615 (Div. 3). B - Collecting Packages

题面:https://codeforces.com/contest/1294/problem/B 题目大意: 机器人从(0,0)开始,他只能往上'U'或者往右'R'走 坐标系中有着很多包裹,分别在一些点上 机器人需要走过去把这些包裹全部收集起来 问能不能做到 如果能,再输出移动方式,相同移动方式输出字典序最小的方案 解题思路: pair或者结构体排序,x与y的优先级任意,因为下一个包裹必定在当前机器人位置右方/上方/右上方 否则直接输出NO,表示不可能存在这种移动方式 在输出移动方式时,注意能先

Codeforces Round #615 (Div. 3) F. Three Paths on a Tree

F. Three Paths on a Tree 原题链接:https://codeforces.com/contest/1294/problem/F 题目大意: 给定一棵树,选出三点,使三点连成的j简单路径最大.简而言之,三个点连成的边的集合大小. 解题思路: 假设任取一点为三点连线的公共点,最长路径就是这个点到其他三个点的三条最长边之和,可知这个点一定在直径上(画图分析假设不在时的最长路径可反证).所以先求出树的直径,在使用$ans =(a b+a c+b c) / 2$遍历可以得到第三个点

Codeforces Round #615 (Div. 3) E. Obtain a Permutation

E. Obtain a Permutation 原题链接:https://codeforces.com/contest/1294/problem/E 题目大意: 给一个无序矩阵,可以进行两个操作: 1.改变任何元素的大小: 2.将任何一列中的元素向上提一位,也就是$a_{1, j}:=a_{2, j}, a_{2, j}:=a_{3, j}, \dots, a_{n, j}:=a_{1, j}$ 使得最后的矩阵变为有序的序列,即$\left.a_{1,1}=1, a_{1,2}=2, \ldot

题解 Codeforces Round #615 (Div. 3) (CF1294)

A:判断一下和是不是3的倍数,由于只加不减,所以还要判断有没有大于和的1/3. 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 int T,a,b,c,n,x; 9 namespace io{ 10 il c

Codeforces Round #615 (Div. 3) 题解

A - Collecting Coins 题意: 给你四个数a,b,c,d,n.问你是否能将n拆成三个数A,B,C,使得A+a=B+b=C+c. 思路: 先计算三个数的差值的绝对值abs,如果abs大于n则肯定不行,如果小于n,还需判断(n-abs)%3是否为0,不为0则不行. #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<vector

Codeforces Round #615(div.3) A 题解

题意: 分别有a,b,c个硬币在对应的三个人手中,我有n个硬币,问如何将这n个硬币分给这三个人使得最后三个人的硬币数相同. 思路: 先求出每个人与最多的人的硬币个数的差距,然后拿n个硬币去填补这个空缺,分过剩下来没有分的如果可以%3==0,则说明可以相同.如果不为0则说明无法分配. 水题一道: #include<iostream> #include<algorithm> using namespace std; int main() { int t; cin>>t; w

Codeforces Round #615(Div.3)解题报告

Codeforces Round #615(Div.3)解题报告 A. Collecting Coins 注意\(n\)可能不够用的情况. #include<bits/stdc++.h> using namespace std; typedef long long ll; int a, b, c, n; void solve() { cin >> a >> b >> c >> n; int mx = max(max(a, b), c); int