【赛时总结】 ◇赛时·I◇ AtCoder ARC-098

◆赛时I◆ ARC-098


■试题&解析■

◆本场最水◆ C-Attention

长点儿信心吧……

  • 【AtCoder ARC-098 C】
  • 【解析】

    既然只存在左右(东西)两个朝向,那么领导右侧的人应朝左,相反左侧的人朝右。则要找到一个人作为领导使上述人的数量最多。

    我们可以用 tot[0]、tot[1] 分别储存最初朝东、西的人的个数。然后从第一个人开始枚举,统计当前人左侧的分别朝向东、西的人的个数,从而算出当前人左侧朝右、右侧朝左的人的个数,记为F。领导人即是算出F最大的人。

    注意统计时要排开当前人的数量(领导人不算在内,不需要改变朝向)。

  • 【源代码】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN int(3*1e5)
int len,tot[2],res[2],ans;
char s[MAXN+5];
int main()
{
    scanf("%d%s",&len,s);
    for(int i=0;i<len;i++)
        tot[s[i]==‘E‘]++;
    ans=1e9;
    for(int i=0;i<len;i++)
    {
        int F=0;
        F+=res[0];
        F+=tot[1]-res[1]-int(s[i]==‘E‘);
        res[s[i]==‘E‘]++;
        ans=min(ans,F);
    }
    printf("%d\n",ans);
    return 0;
}

◆脑壳开窍◆ D-Xor Sum 2

没办法,作者就是脑壳不开窍啊 QwQ

  • 【AtCoder ARC-098 D】
  • 【解析】

    其实这道题我没有看出来我哪里TLE了,和正解的算法一样——滑动窗口,可能是写的丑吧。

对于异或有一个技巧——如果 A^B==A+B ,则 A&B==0 即A、B的二进制的各个数位都不相同。现在问题就变成寻找一个区间 [l,r] 使得 Ai&Aj=0

(i≠j 且 l≤i,j≤r)。

定义区间左右端点l、r,并初始化l=1,r=0。保证 r < n(即 r+1≤n 且 l≤r )。定义当前区间的所有数异或所得到的值为F,初始化为0。

若 A[r+1]&F==0 即当前区间向右扩充1后,仍然满足所给条件,则更新F、r,向右扩充,并同时更新ans,增加的答案个数为扩充后区间的长度。用while循环执行此操作。

第一次while循环结束后,则要么枚举完了,要么 F&A[r+1]!=0 ,此时无论如何向右扩充都无法满足题目所给条件,所以只能删除左侧,直到再次满足 F&A[r+1]==0 (当区间为空时,也满足 F&A[r+1]==0 )。

注意:ans用 long long 储存。

  • 【源代码】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=2*1e5;
int n,A[MAXN+5];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&A[i]);
    int l=1,r=0,F=0;
    long long ans=0;
    while(r<n)
    {
        while(r<n && !(F&A[r+1]))
        {
            r++;ans+=r-l+1;
            F^=A[r];
        }
        while(l<=r && (F&A[r+1]))
            F^=A[l++];
    }
    printf("%lld\n",ans);
    return 0;
}

◆想不到吧◆ E - Range Minimum Queries

这个是真的想不到 (u_u)

  • 【AtCoder ARC-098 E】
  • 【解析】

    对答案有影响的变量主要是最大值和最小值,那么就可以先通过枚举限制其中一个变量(这里我用最小值)。

    限制最小值,也就是说枚举Ai,在选取区间时,区间中最小的元素不能小于Ai。这样我们就可以将 A 分成多个段——每个段中的元素都大于等于Ai。这样就限制了区间中取到的最小值,但是此时的最小值不一定是Ai(比如枚举到的Ai=2,则当k=2时数据“1 2 1”就取不到2)。最小值确定后,要使最大值减最小值最小,则需要让最大值尽量小,即抽取到的数要尽量小。

    那么我们可以提取出各个满足长度大于等于k的段。这些段可以作为选取区间的段,且设段的长度为len,我们可以在这个段里取 len-k+1 次区间(每一次选取都会使段的长度减少1,直到区间长度小于k)。可见如果取 len-k+1 次区间,则一定可以取出这个段里前 len-k+1 小的数。

    为了使取出的数尽量小,我们需要尽量使每个段中取出的数都尽量小,也就是段中前 len-k+1 小的数。我们可以将这些数存入另外一个数组(pri),方便最后找到最小的最大值。由于我们要进行Q次抽取,最小的最大值一定是 pri 中第 Q 小的数,而最小值就是 pri 中最小的数。

  • 【源代码】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=2000;
const int INF=(int)1e9+5;
int n,k,q,A[MAXN+5],ans=INF;
void SOLVE(int x)
{
    vector<int> pri;
    int i=0;
    while(i<n)
    {
        vector<int> que;
        while(A[i]<x && i<n) i++;
        while(A[i]>=x && i<n) que.push_back(A[i++]);
        if(que.size()>=k)
        {
            sort(que.begin(),que.end());
            for(int j=0;j<(int)que.size()-k+1;j++)
                pri.push_back(que[j]);
        }
    }
    sort(pri.begin(),pri.end());
    if((int)pri.size()>=q)
        ans=min(ans,pri[q-1]-pri[0]);
}
int main()
{
    scanf("%d%d%d",&n,&k,&q);
    for(int i=0;i<n;i++)
        scanf("%d",&A[i]);
    for(int i=0;i<n;i++)
        SOLVE(A[i]);
    printf("%d\n",ans);
    return 0;
}

(F题真的不会做了,请各位神牛多多指点)


The End

Thanks for reading!

-Lucky_Glass

原文地址:https://www.cnblogs.com/LuckyGlass-blog/p/9107091.html

时间: 2024-10-13 18:08:15

【赛时总结】 ◇赛时·I◇ AtCoder ARC-098的相关文章

ARC 098 D - Xor Sum 2

Problem Statement There is an integer sequence A of length N. Find the number of the pairs of integers l and r (1≤l≤r≤N) that satisfy the following condition: Al xor Al+1 xor - xor Ar=Al + Al+1 + - + Ar Here, xor denotes the bitwise exclusive OR. Def

【题解】 AtCoder ARC 076 F - Exhausted? (霍尔定理+线段树)

题面 题目大意: 给你\(m\)张椅子,排成一行,告诉你\(n\)个人,每个人可以坐的座位为\([1,l]\bigcup[r,m]\),为了让所有人坐下,问至少还要加多少张椅子. Solution: 为什么加椅子?我们可以在最左边或最右边一直加直到人人都有座位. 首先这道题目抽象成二分图很简单,然后我们可以只要求解出人与座位的最大匹配是多少,总人数减去即可,但跑二分图最大匹配显然会超时,我们就可以往霍尔定理方面想. 然后你还需要知道一个霍尔定理推论:假设某个人的集合为\(X\),这个集合所对应的

【题解】Atcoder ARC#90 E-Avoiding Collision

自己做出来固然开心,但是越发感觉到自己写题的确是很慢很慢了……往往有很多的细节反反复复的考虑才能确定,还要加油呀~ 这道题目的突破口在于正难则反.直接求有多少不相交的不好求,我们转而求出所有相交的.我们先预处理出由 \(S\) 到 \(T\) 的最短路图(跑一边Dijkstra,所有的最短路径构成的图),显然可以顺便处理出 \(T\) 到 \(S\) 的.然后这个图是一个拓扑图,满足的性质就是从 \(S\) 点出发的任意一条路径终点均为 \(T\) 且为二者之间的最短路.拓扑图dp对于每个点我们

【赛时总结】 ◇赛时&#183;II◇ AtCoder ABC-100

◆赛时·II◆ ABC-100 ■唠叨■ ABC终于超过百场比赛啦(毫不犹豫地参加).然后莫名其妙的好像是人很多,评测慢得不可理喻.然后我就--交了一大发--错误程序--然后B题就没了.最后的D题居然是贪心(题意没看懂),我就做了个DP还wa了 (:′⌒`) ■试题&解析■ ◆泼水节◆ A-Happy Birthday! [Atcoder ABC-100 A] [翻译] E869120和square1001的16岁生日到了,来自Atcoder王国的Takahashi送给他们一个被平均切成16份的

【赛时总结】◇赛时&#183;VII◇ Atcoder ABC-106

[赛时·VII] ABC-106 一条比赛时莫名其妙发了半个小时呆的菜鸡&咸鱼得到了自己应有的下场--279th. Rating:1103(+) 终于AK,一次通过-- ◇ 简单总结 ABC还是和往常一样,前两道题比手速(+英语QwQ,那些dalao七分钟AK时我还在看第二题的题意??),感觉自己码代码的速度还是太慢了. 第三题稍动脑筋,发现是一道结论题-- 第四题本来没什么难度,但是我时间复杂度分析错了,一直以为我会TLE,就没敢交??,然后开始想优化(实际上发了半个小时呆),于是rank就蹭

【赛时总结】◇赛时&#183;V◇ Codeforces Round #486 Div3

◇赛时·V◇ Codeforces Round #486 Div3 又是一场历史悠久的比赛,老师拉着我回来考古了--为了不抢了后面一些同学的排名,我没有做A题 ◆ 题目&解析 [B题]Substrings Sort +传送门+   [暴力模拟] 题意 给出n个字符串,你需要将它们排序,使得对于每一个字符串,它前面的字符串都是它的子串(对于字符串i,则字符串 1~i-1 都是它的子串). 解析 由于n最大才100,所以 O(n3) 的算法都不会爆,很容易想到暴力模拟. 如果字符串i是字符串j的子串

AtCoder Regular Contest 098

AtCoder Regular Contest 098 C - Attention 题意 给定一个只包含"E","W"字符串,可以花一的花费使他们互相转换.选定一个位置,使位置左边的字符都变成E,右边都变成W所需要的最小花费. 分析 这题纯粹是签到题,做两个前缀和然后直接加就可以了. #include <iostream> #include <cmath> #include <cstring> #include <cstdi

【Atcoder】ARC 080 E - Young Maids

[算法]数学+堆 [题意]给定n个数的排列,每次操作可以取两个数按序排在新序列的头部,求最小字典序. [题解] 转化为每次找字典序最小的两个数按序排在尾部,则p1和p2的每次选择都必须满足:p1在当前序列的奇数位置,p2在当前序列的偶数位置且位于p1之后.满足条件的情况下每次找最小. 每次找到p1和p2都把序列划分为3部分,递归进行,初步想到使用归并. 进一步考虑性质,每对数字要出现必须它的上属序列的p1和p2必须出现,此外没有其他要求. 所以用优先队列维护每个序列,序列的优先级为p1,每次处理

【AtCoder】 ARC 103

link C-//// 直接算会出现奇偶两组选了同一个数,注意处理一下就行 #include<bits/stdc++.h> #define ll long long #define dbg1(x) cerr<<#x<<"="<<(x)<<" " #define dbg2(x) cerr<<#x<<"="<<(x)<<"\n&quo