acwing 62周赛

第62场周赛心得

前面的周赛都没有记录,因为博客的原因。

切入正题

T1.三个元素


题面: 给定序列\(a_1,a_2,a_3,....,a_n\),请找出三个元素\(r_1,r_2,r_3\),使得\(r_1 < r_2 < r_3\)


\(T1\)一般是打卡题,这次虽然不出意外的和之前一样简单,但是因为是速度赛,所以在审题上马虎了。

简直简单的抠脚了,结果WA了一次…… 。

不说。

AC code

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define in inline
#define rint register int
typedef long long LL;
typedef pair<int,int> PII;

in int read()
{
    rint x=0,f=0; register char ch=getchar();
    while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return f?-x:x;
}

/*----------code----------*/
const int N=1e5+10;
PII a[N];
int n,m,k;

int main()
{
    n=read();
    for(int i=1;i<=n;i++) a[i].first=read(),a[i].second=i;

    sort(a+1,a+n+1);
    int res=0;

    vector<int> v;
    for(int i=1;i<=n&&v.size()<=2;i++)
        if(a[i].first>a[i-1].first) v.push_back(a[i].second);

    if(v.size()<3) puts("-1 -1 -1");
    else
        for(int i=0;i<3;i++) cout<<v[i]<<' ';

    return 0;
}

T2.收集卡牌


简化题面:

\(n\)次操作,每次读入一个1~m的数,请问在每次操作之后,是否能集齐所有数字(1 ~ m)。

如果集齐并兑换了一次,那么兑换出去的卡牌就不属于你了(需要减去)。

请输出每一次操作后的状态(不能集齐就是0,能就是1)

样例:
3 11
2 3 1 2 2 2 3 2 2 3 1

输出:
00100000001

按照比赛经验,第二题应该是优化题(贪心,数据结构,前缀和差分等)。

这一题最初看到范围是十万,于是就想到\(O(n*log \ n)\)的做法。

又因为每个卡牌号1到m,所以想到了树状数组的做法。

后来又发现树状数组的方法会绕弯,那么转到\(O(n)\)

线性做法发现这题直接暴力可以过(想不到吧)。

用哈希表存储每一个卡牌的数量,然后记录目前集齐了多少种卡牌。

算法是模拟,直接暴力:

AC code

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define in inline
#define rint register int
typedef long long LL;
typedef pair<int,int> PII;

in int read()
{
    rint x=0,f=0; register char ch=getchar();
    while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return f?-x:x;
}

/*----------code----------*/
const int N=1e5+10;
int a[N];
int n,m,k;

int main()
{
	m=read(),n=read();
	for(int i=0;i<n;i++) a[i]=read();

	string res="";
	int cnt=0,st[N];
	memset(st,0,sizeof st);
	
	for(int i=0;i<n;i++)
	{
	    if(!st[a[i]]) cnt++;
	    st[a[i]]++;
	    
	    if(cnt==m)
	    {
	        res+='1';
	        for(int i=1;i<=m;i++)
	            if(!--st[i]) cnt--;
	    }
	    else res+='0';
	}
	
	cout<<res;
    
    return 0;
}

T3.集合操作

题面已经最简,所以不再简化。

本题为计算题,考验数学分析能力。

数学证明分三个步骤,具体见这一篇题解

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define in inline
#define rint register int
typedef long long LL;
typedef pair<int,int> PII;

in int read()
{
    rint x=0,f=0; register char ch=getchar();
    while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return f?-x:x;
}

/*----------code----------*/
const int N=5e5+10;
int a[N];
int n=0,m,k;

int main()
{
    m=read();
    
    double res=0,sum=0;
    
    while(m--)
    {
        int op=read();
        if(op==1)
        {
            a[++n]=read();
            while(k+1<=n&&a[k+1]<=(sum+a[n])/(k+1)) sum+=a[++k];
            res=max(res,a[n]-(sum+a[n])/(k+1));
        }
        else printf("%.6lf\n",res);
    }
    return 0;
}

结尾

在文末添加一下自己的想法。

题目都不是很难,前两题小于等于普及组,第三题大于普及组,小于提高组。

诶,只能说多刷题培养灵感吧。

posted @ 2022-07-30 22:03  Sankano  阅读(31)  评论(0编辑  收藏  举报