zoukankan      html  css  js  c++  java
  • 【赛时总结】 ◇赛时·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
    ",ans);
    	return 0;
    }
    
    

    ◆脑壳开窍◆ D-Xor Sum 2

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

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

    对于异或有一个技巧——如果 A^BA+B ,则 A&B0 即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]&F0 即当前区间向右扩充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
    ",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
    ",ans);
    	return 0;
    }
    
    

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


    The End

    Thanks for reading!

    -Lucky_Glass

    欢迎转载٩(๑❛ᴗ❛๑)۶,请在转载文章末尾附上原博文网址~
  • 相关阅读:
    顺序栈的初始化,建立,插入,查找,删除。
    循环单链表的初始化,建立,插入,查找,删除。
    双链表的初始化,建立,插入,查找,删除。
    CSS轮廓
    CSS框模型
    CSS字体
    CSS层叠样式表的分类:
    CSS 背景
    利用visio2003进行数据库的反向工程
    CSS 选择器分类
  • 原文地址:https://www.cnblogs.com/LuckyGlass-blog/p/9107091.html
Copyright © 2011-2022 走看看