AtCoder Regular Contest 098

比赛链接:https://arc098.contest.atcoder.jp/assignments

C:输入一个n,接下来输出一个长度为n的字符串,w为向西,e为向东,让找出一个人当领队,使其他所有人面向他,问怎样才能使人数转向最小(水题)

//先从左边先行扫描一遍,再从右边扫描一遍,两边加起来直接用总人数相减   
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <string>
     
    using namespace std;
     
    const int maxn=1e6+10;
     
    int n;
    int l[maxn],r[maxn];
    char str[maxn];
    int maxx=0;
     
    int main()
    {
        scanf("%d",&n);
        scanf("%s",str);
     
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
     
        for(int i=0;i<n;i++)
        {
            l[i]=l[i-1];
            if(str[i]=='E') {
                    l[i]++;
            }
        }
     
        for(int i=n-1;i>=0;i--)
        {
            r[i]=r[i+1];
            if(str[i]=='W') {
                    r[i]++;
            }
        }
     
     
         for(int i=0;i<n;i++) {
            r[i]=r[i]+l[i];
            maxx=max(r[i],maxx);
         }
     
         cout<<n-maxx<<endl;
     
     
     
     
        return 0;
    }

D - Xor Sum 2

题意:给出n个数,求它的连续子序列中,满足下列公式,(l,r)的对数有多少对

Al xor Al+1 xor … xor Ar=Al Al+1 + … Ar

思路:由题意可以得到,连续子序列,如果在ai这个数不符合公式的话,即之后的符合条件的对数中将不在需要这个元素,所有枚举元素来计算符合公式的对数 。

    #include <bits/stdc++.h>
     
    using namespace std;
     
    int n;
     
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n;
        vector<long long>a(n+1),xo(n+1),sum(n+1);
     
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            xo[i]=a[i]^xo[i-1];
            sum[i]=sum[i-1]+a[i];
        }
     
        long long l=0,ans=0;
        for(int i=1;i<=n;i++)
        {
            while((xo[i]^xo[l])!=sum[i]-sum[l])
            {
                l++;
            }
            ans+=i-l;
        }
     
        cout<<ans<<endl;
     
     
        return 0;
    }

E - Range Minimum Queries

/*
本题因为要求n个连续数中取q个k长的子段,要找出每个子段最小的数,使这些最小的数中的最大的数-最小的数中的最小的数最小(不能有重复的数)
所以就可以大致归为在1-n个数中把每个数都看为最小(暂且成为A),并1-n中找到每个大于等于该数的数,当这些数的位置-A的位置>=子序列应该有
的长度的时候进行排序,当这些子序列中第q个元素-A即为当前中最小的,最后再从所有的数中找到最小的即可
*/

#include <bits/stdc++.h>

using namespace std;

int inf=0x3f3f3f3f;
int n,k,q;
long long a[2010],t[2010],al[2010];

int work(int x)
{
    int s=0,num=0,j;
    for(int i=1;i<=n+1;i++)
    {
        if(a[i]>=a[x])
        {
            if(s==0) s=i;//标记大于等于该数的位置
        }
         else if(s)
            {
                if(i-s>=k)
                //如果该数的位置减去要扫描的数的位置大于等于要求的区间,
                {
                    for(j=s;j<i;j++)//s为大于该数的起始位置
                    {
                        t[j-s+1]=a[j];//用数组t来记录这一个区间的数
                    }
                    sort(t+1,t+i-s+1);//对数组t进行排序
                    for(j=1;j+k-1<=i-s;j++)
                    //该区间因为是连续的,类似于5个数k=3时能取三段数,并用al数组记录
                    {
                        num++;
                        al[num]=t[j];
                    }
                }
                s=0;//位置归到0
            }
    }
    if(num<q) return inf;
    sort(al+1,al+num+1);
    return al[q]-a[x];
}



int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>k>>q;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans=inf;
    for(int i=1;i<=n;i++) ans=min(ans,work(i));
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Fy1999/p/9102158.html