AcWing第62场周赛地址
4500. 三个元素
题目
给定一个长度为 n n n 的数组 r 1 , r 2 , … , r n r_1,r_2,…,r_n r1,r2,…,rn。
请你找到其中的三个元素 r a , r b , r c r_a,r_b,r_c ra,rb,rc,使得 r a < r b < r c r_a < r_b < r_c ra<rb<rc 成立。
思路
先记录一个结构体数组 a a a ,包含元素的值和下标。
然后按元素的值 s o r t sort sort 排序一下,使得 r a ≤ r b ≤ r c r_a \le r_b \le r_c ra≤rb≤rc 成立。
最后记录元素值只出现一次的元素,使得 r a < r b < r c r_a < r_b < r_c ra<rb<rc 成立。
判断非重复的元素的个数是否大于等于 3 3 3 , 是则输出前三个记录的元素的下标,否则输出 − 1 − 1 − 1 -1 -1 -1 −1−1−1 。
C o d e Code Code
#include<bits/stdc++.h>
using namespace std;
int n;
struct node
{
int id,num;
}a[3001];
bool cmp(node a,node b)
{
return a.num<b.num;
}
int s[3001],len;
int main()
{
cin>>n;
for(int i=1; i<=n; i++)
{
cin>>a[i].num;a[i].id=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1; i<=n; i++)
{
if(a[i].num!=a[i-1].num)
{
s[++len]=a[i].id;
}
}
if(len<3)cout<<"-1 -1 -1"<<endl;
else
cout<<s[1]<<" "<<s[2]<<" "<<s[3]<<endl;
}
4501. 收集卡牌
题目
某干脆面厂商在每包面中都放置有一张武将卡。
武将卡共分为 n n n 种,编号 1 ∼ n 1 \sim n 1∼n。
当集齐 1 ∼ n 1 \sim n 1∼n 号武将卡各一张时,就可以拿它们去换大奖。
为了换大奖,李华先后购买了 m m m 包该品牌的干脆面。
其中第 i i i 包面中包含的武将卡的编号为 a i a_i ai。
每当买完一包面,得到该面赠送的武将卡后,李华都会审视一遍自己手中的全部卡牌。
如果此时自己现有的卡牌能够凑齐全部武将卡,那么他就会立即将每种武将卡都拿出一张,并将拿出的卡牌寄给厂商,用来换奖。
请你分析李华购买干脆面的整个过程并计算购买完每一包面后,李华能否凑齐全部武将卡用来换奖。
注意,每次换奖都需要消耗卡牌,消耗掉的卡牌就不属于他了。
思路
设换了 n o w now now 次奖, s x s_x sx 为卡牌数量大于等于 x x x 的卡牌种类的个数(不换一次奖)。
每收集一张卡牌 a i a_i ai ,卡牌 a i a_i ai 的数量 t [ a i ] t[a_i] t[ai] 加一,卡牌数量大于等于 t [ a i ] t[a_i] t[ai] 的卡牌种类 s [ t [ a i ] ] s[t[a_i]] s[t[ai]] 加 1 1 1 ( t [ a i ] t[a_i] t[ai] 已经加过一)。
若 s n o w + 1 = = n s_{now+1} == n snow+1==n ,则表示可以换第 n o w + 1 now + 1 now+1 次奖,输出 1 1 1 , n o w now now 加一。
否则输出 0 0 0 。
C o d e Code Code
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[100001];
int s[100001];
int now,t[100001];
int main()
{
cin>>n>>m;
for(int i=1; i<=m; i++)
{
cin>>a[i];
t[a[i]]++;
s[t[a[i]]]++;
if(s[now+1]==n)
{
cout<<1;now++;
}
else cout<<0;
}
}
4502. 集合操作
题目
给定一个由正整数(最初为空)组成的多重集 S S S。多重集表示可能存在重复元素的集合。
请你对该集合执行 Q Q Q 次操作,操作分为两种:
- 增加操作,格式为
1 x
,将一个正整数 x x x 加入到集合 S S S 中。数据保证, x x x 不小于当前 S S S 中的任何元素。 - 询问操作,格式为
2
,找到一个当前 S S S 的子集 s s s ,要求 m a x ( s ) − m e a n ( s ) max(s)-mean(s) max(s)−mean(s) 的值应尽可能大,输出 m a x ( s ) − m e a n ( s ) max(s)-mean(s) max(s)−mean(s) 的最大可能值。 m a x ( s ) max(s) max(s) 表示 s s s 中最大元素的值, m e a n ( s ) mean(s) mean(s) 表示 s s s 中所有元素的平均值。
思路
数据保证, x x x 不小于当前 S S S 中的任何元素。
其实自己在比赛的思路是正确的,但是没看到题目的数据保证就没写这一题,然后窝就去写另外两题的题解了(在比赛结束后才提交题解)。
大小为 n o w now now 的子集一定为 前 n o w − 1 now-1 now−1 个元素(使平均值最小)和第 n n n 个元素(使子集的最大值最大)。
前 x x x 个数字的平均值可以用前缀和预处理。
C o d e Code Code
#include<bits/stdc++.h>
using namespace std;
double sum[500001],a[500001];
int Q,now=1,n;
int main()
{
cin>>Q;
while(Q--)
{
int op;
cin>>op;
if(op==1)
{
cin>>a[++n];
sum[n]=a[n]+sum[n-1];
}
else
{
while(now<n&&a[n]-((sum[now]+a[n])/(now+1))>a[n]-((sum[now-1]+a[n])/now))now++;
printf("%.6lf\n",a[n]-((sum[now-1]+a[n])/now));
}
}
}