Codeforces Round #657 (Div. 2) (A-D)

还好没在线打,这场属实搞心态。

题目:A. Acacius and String
题意:构成一个字符串中只有一个abacaba的子串,?可以随意填。

枚举?所构成的是子串abacaba的第几位,之后在遍历整个串是否只有一个,不成立还原继续。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e5+10;
double eps=1e-4;
char s[66];
char hh[66]="abacaba";
int main()
{
     
    int T;
    scanf("%d",&T);
    while(T--)
    {
     
        int n,i,j;
        scanf("%d",&n);
        scanf("%s",s+1);
        int sum=0;
        for(i=1;i<=n;i++)
        {
     
            if(s[i]=='a')
            {
     
                int len=1;
                for(j=i+1;j<=n&&len<=6;j++)
                {
     
                    if(s[j]==hh[len])
                    {
     
                        len++;
                        continue;
                    }
                    else
                        break;
                }
                if(len==7)
                {
     
                    sum++;
                }
            }
        }
        if(sum==1)
        {
     
            printf("YES\n");
            for(i=1;i<=n;i++)
            {
     
                if(s[i]=='?')
                {
     
                    printf("z");
                    continue;
                }
                printf("%c",s[i]);
            }
            printf("\n");
            continue;
        }
        if(sum>1)
        {
     
            printf("NO\n");
            continue;
        }
        bool bo=false;
        for(i=1;i<=n;i++)
        {
     
            if(s[i]=='?')
            {
     
                bool op=false,flag=false;
                for(j=0;j<=6;j++)
                {
     
                    if(i-j>=1&&(i+6-j<=n))
                    {
     
                        char temp[10];
                        int len=0;
                        op=true;
                        flag=false;
                        for(int k=i-j;k<=i+6-j;k++)
                            temp[len++]=s[k];
                        len=0;
                        for(int k=i-j;k<=i+6-j;k++)
                        {
     
                            if(s[k]=='?')
                            {
     
                                s[k]=hh[len++];
                                continue;
                            }
                            if(s[k]!=hh[len])
                            {
     
                                op=false;
                                break;
                            }
                            len++;
                        }
                        if(!op)
                        {
     
                            len=0;
                            for(int k=i-j;k<=i+6-j;k++)
                                s[k]=temp[len++];
                            continue;
                        }
                        int cnt=0;
                        for(int k=1;k<=n;k++)
                        {
     
                            if(s[k]=='a')
                            {
     
                                int llen=1;
                                for(int kk=k+1;kk<=n&&llen<=6;kk++)
                                {
     
                                    if(s[kk]==hh[llen])
                                    {
     
                                        llen++;
                                        continue;
                                    }
                                    else
                                        break;
                                }
                                if(llen==7)
                                {
     
                                    cnt++;
                                }
                            }
                        }
                        if(cnt==1)
                        {
     
                            flag=true;
                            break;
                        }
                        len=0;
                        for(int k=i-j;k<=i+6-j;k++)
                            s[k]=temp[len++];
                    }
                }
                if(op&&flag)
                {
     
                    bo=true;
                    break;
                }
            }
        }
        if(bo)
        {
     
            printf("YES\n");
            for(i=1;i<=n;i++)
            {
     
                if(s[i]=='?')
                {
     
                    printf("z");
                    continue;
                }
                printf("%c",s[i]);
            }
            printf("\n");
        }
        else
            printf("NO\n");
    }
    return 0;
}

题目:B. Dubious Cyrpto

题意:给定l,r,m,在[l,r]内找到a,b,c, n ∗ a + b − c = m n*a+b−c=m na+bc=m,n为任意正整数。

枚举a,m%a,判断b-c范围一定在[l-r,r-l]中。当a>m时一种情况,之后取余,以及判断b-c为负数的情况别漏了。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e5+10;
double eps=1e-4;
int main()
{
     
    int T;
    scanf("%d",&T);
    while(T--)
    {
     
        ll i,j,l,r,m;
        scanf("%lld %lld %lld",&l,&r,&m);
            for(i=l;i<=r;i++)
            {
     
                if(m<i)
                {
     
                    if(l<=(r-i+m))
                    {
     
                        printf("%lld %lld %lld\n",i,r-i+m,r);
                        break;
                    }
                    continue;
                }
                ll temp2=m%i;
                if(temp2+l<=r)
                {
     
                    printf("%lld %lld %lld\n",i,l+temp2,l);
                    break;
                }
                ll temp1=(m/i+1)*i-m;
                if(l+temp1<=r)
                {
     
                    printf("%lld %lld %lld\n",i,r-temp1,r);
                    break;
                }
            }
    }
    return 0;
}
 

题目:C. Choosing flowers

题意:有m种花(每种无限数量),送n朵花,第一次收到的就加a[i],之后的都是b[i],问值最大。

一开始分析的是找到最大的b[i],筛掉大于b[i]的a[i],剩下的全部都拿b[i],仔细分析显然是错的,考虑不到所有的情况,有可能拿第二大的b[i]。可以发现,我们肯定要确定拿一种花我们之后全是拿他是主要的花。枚举主要拿的是第几种,a[i]用前缀和,加二分把大于b[i]的a[i]拿掉,每种情况都考虑维护一个最大值。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e5+10;
double eps=1e-4;
ll a[100010],b[100010];
ll c[100010];
ll sum[100010];
struct RatioComp
{
     
    bool operator()(const pair<int, int>& A, const pair<int, int>& B)
    {
     
            return A.first>B.first;
    }
};
int main()
{
     
    int T;
    scanf("%d",&T);
    while(T--)
    {
     
     //   multiset,RatioComp>hh;
        ll n,m,i,j;
        scanf("%lld %lld",&n,&m);
        ll MAX=0;
        for(i=1;i<=m;i++)
        {
     
            scanf("%lld %lld",&a[i],&b[i]);
            c[i]=a[i];
            MAX=max(b[i],MAX);
        }
        sum[0]=c[0]=0;
        sort(c+1,c+1+m);
        for(i=1;i<=m;i++)
            sum[i]=sum[i-1]+c[i];
        ll ans=c[m];
        sum[m+1]=0;
        for(i=1;i<=m;i++)
        {
     
            int pos=upper_bound(c,c+1+m,b[i])-c;
            if(pos>m)
            {
     
                ans=max(ans,(n-1)*b[i]+a[i]);
                continue;
            }
            if(!pos)
            {
     
                if(n<=m)
                {
     
                    ans=max(ans,sum[m]-sum[m-n]);
                }
                else
                {
     
                    ll temp=sum[m]+(n-m)*MAX;
                    ans=max(ans,temp);
                }
                continue;
            }
            if(m-pos+1>=n)
            {
     
                ans=max(ans,sum[m]-sum[m-n]);
                continue;
            }
            ll cnt=n-(m-pos+1);
            ll num=sum[m]-sum[pos-1];
            if(a[i]>b[i])
                num+=cnt*b[i];
            else
                num+=(cnt-1)*b[i]+a[i];
            ans=max(ans,num);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

题目:D. New Passenger Trams

题意:一天h小时,一小时m分钟(偶数),有客车和货车客车需要提前k分钟空出时间上下车,如果货车在这个时间段则要删除,(不包括端点,端点的货车不需要删除),客车每半小时发一辆,问最小删除的货车数以及客车最好的发车时间。(第一列发车时间t一定在0–m/2)内。

可以发现和h无关,我们只需要考虑m,因为每半小时就发一辆,(t-k,t)…(t-k+m/2,t+m/2)…。仔细考虑如果在某一时刻是最优的情况,那么在这个圆上是可以移动的,整个的发车时间跟着移动,一旦有一个发车时间与货车的发车时间重叠就不能移动了。那么我们找到了枚举的方向,枚举n辆货车的发车时间与客车的端点重合的情况,m范围太大是不能枚举的。我们预处理出每辆货车在半小时内的情况,排序就可以二分了。具体见代码。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e5+10;
double eps=1e-4;
vector<ll>hh;
vector<ll>sorted;
int main()
{
     
    ll n,m,i,j,h,k;
    scanf("%lld %lld %lld %lld",&n,&h,&m,&k);
    for(i=0;i<n;i++)
    {
     
        ll xx,yy;
        scanf("%lld %lld",&xx,&yy);
        hh.push_back((xx*m+yy)%(m/2));
        sorted.push_back(hh[i]);
    }
    sort(sorted.begin(),sorted.end());
    ll ans=llinf;
    ll bestt=0;
    for(i=0;i<sorted.size();i++)
    {
     
        if(sorted[i]+k<m/2)
        {
     
            j=lower_bound(sorted.begin(),sorted.end(),sorted[i]+k)-sorted.begin();
            ll cnt=j-i-1;
            if(cnt<ans)
            {
     
                ans=cnt;
                bestt=sorted[i];
            }
        }
        else
        {
     
            j=lower_bound(sorted.begin(),sorted.end(),sorted[i]+k-m/2)-sorted.begin();
            ll cnt=(int)sorted.size()-i+j-1;
            if(cnt<ans)
            {
     
                ans=cnt;
                bestt=sorted[i];
            }
        }
    }
    printf("%lld %lld\n",ans,(bestt+k)%(m/2));
    ll t=bestt;
    for(j=0;j<hh.size();j++)
    {
     
        ll x=hh[j];
        if(t+k>m/2)
        {
     
            if(x>t||x<t+k-m/2)
            {
     
                printf("%lld ",j+1);
            }
        }
        else
        {
     
            if(x>t&&x<t+k)
            {
     
                printf("%lld ",j+1);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(Codeforces Round #657 (Div. 2) (A-D))