• Codeforces Round #466 (Div. 2)


    (题目真是大水,居然没有打,气人)

    A. Points on the line

    题意:n个点,删除一些点,使得剩下点两两距离不超过d,求删除点的最少个数

    题解:暴力即可

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int Max(int a,int b){return a>b?a:b;}
    inline int read()
    {
        int x=0;char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x;
    }
    int main()
    {
        int n,d,a[105],ans=-1;
        n=read();d=read();
        for(int i=1;i<=n;i++) a[i]=read();
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++)
        {
            for(int j=n;j>=i;j--)
            {
                if(a[j]-a[i]<=d)
                {
                    ans=Max(ans,j-i+1);
                    break;
                }
            }
        }
        printf("%d",n-ans);
        return 0;
    }
    View Code

    B. Our Tanya is Crying Out Loud

    题意:一个数初始为n,可以将它减1(花费A代价),或除以k(必须整除,花费B代价),求最小代价

    题解:最优策略肯定是先减到能除的最大值,然后除,然后继续减,直到除比减花费更大时,剩下全减,最坏复杂度是logn的,k==1时特判

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline long long read()
    {
        long long x=0;char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x;
    }
    long long n,k,A,B,ans,now;
    int main()
    {
        n=read();k=read();A=read();B=read();
        if(k==1)
        {
            printf("%I64d ",(n-1)*A);
            return 0;
        }
        now=n;
        while(now>1)
        {
            ans+=(now%k)*A;now-=now%k;
            if(now==1) break;
            if((now-now/k)*A<B)
            {
                ans+=(now-1)*A;
                break;
            }
            ans+=B;
            now/=k;
        }
        printf("%I64d",ans);
        return 0;
    }
    View Code

    C. Phone Numbers

    题意:给你n,k和长度为n的字符串s,求一个由s中字母组成的,长度为k,字典序最小的字符串t,使得t的字典序大于s

    题解:把s中所含字母按字典序排个序,然后从后往前枚举t的哪一位大于s

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x=0;char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x;
    }
    int n,k,r[2005],cnt,has[2005];
    char s[100005];
    bool vis[1000];
    int main()
    {
        n=read();k=read();
        scanf("%s",s);
        for(int i=0;i<n;i++) if(!vis[(int)(s[i])]) r[++cnt]=(int)(s[i]),vis[(int)(s[i])]=1;
        sort(r+1,r+cnt+1);
        for(int i=1;i<=cnt;i++) has[r[i]]=i;
        if(k>n)
        {
            printf("%s",s);
            for(int i=n;i<k;i++) printf("%c",(char)(r[1]));
            return 0;
        }
        for(int i=k-1;i>=0;i--)
        {
            if(has[(int)(s[i])]!=cnt)
            {
                for(int j=0;j<i;j++) printf("%c",s[j]);
                printf("%c",(char)(r[has[(int)(s[i])]+1]));
                for(int j=i+1;j<k;j++) printf("%c",(char)(r[1]));
                break;
            }
        }
        return 0;
    }
    View Code

    D. Alena And The Heater

    题意:给定数组a,b',和一系列与l,r有关的运算规律,求l,r,使得用a造出的数组b等于b',保证有解

    题解:b'中每一位都可以转换成和l,r有关的不等式,随便求求就好了

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int Min(int a,int b){return a<b?a:b;}
    int Max(int a,int b){return a>b?a:b;}
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*f;
    }
    int n,a[100005],b[100005],ll=-1000000001,lr=1000000000,rl=-1000000000,rr=1000000001,len;
    int main()
    {
        int ma,mi;
        char B[100005];
        n=read();for(int i=1;i<=n;i++) a[i]=read();
        scanf("%s",B);
        len=strlen(B);
        for(int i=0;i<len;i++) b[i+1]=B[i]-'0';
        for(int i=5,j;i<=n;i++)
        {
            ma=-1000000005;mi=1000000005;
            for(int j=i;j>=i-4;j--) mi=Min(a[j],mi),ma=Max(a[j],ma);
            if(b[i]==b[i-1])
            {
                for(j=i-2;j>=i-4;j--) if(b[j+1]!=b[j]) break;
                if(j<i-4)
                {
                    if(b[i]) rl=Max(rr,ma);
                    else lr=Min(ll,mi);
                }
            }
            else
            {
                if(b[i]) ll=Max(ll,ma);
                else rr=Min(rr,mi);
            }
        }
        printf("%d %d",ll+1,rr-1);
        return 0;
    }
    View Code

    E. Cashback

    题意:给定一段序列,将他们分为诺干段,每一段的价值为这段数字总和减去前(它的长度/c)小的值

    题解:DP,dp[i]表示断点为i,一定是分成长度为c比较赚,转移:dp[i]=Min(dp[i-1]+a[i],dp[i-c]+sum[i]-sum[i-c]-(i-c到c的最小值))最小值单调队列(或rmq)维护即可

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    long long Min(long long a,long long b){return a<b?a:b;}
    inline long long read()
    {
        long long x=0;char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x;
    }
    long long n,c,a[100005],dp[100005],que[100005],cnt,tail=1,sum[100005];
    void xiu(long long x,long long now)
    {
        que[++cnt]=x;
        while(cnt>tail&&a[que[cnt]]<=a[que[cnt-1]]) que[--cnt]=que[cnt+1];
        while(now>que[tail]&&tail<=cnt) tail++;
    }
    int main()
    {
        n=read();c=read();
        for(long long i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
        for(long long i=1;i<c&&i<=n;i++) dp[i]=dp[i-1]+a[i],xiu(i,0);
        for(long long i=c;i<=n;i++) xiu(i,i-c+1),dp[i]=Min(dp[i-1]+a[i],dp[i-c]+sum[i]-sum[i-c]-a[que[tail]]);
        printf("%I64d
    ",dp[n]);
        return 0;
    }
    View Code

    F. Machine Learning

    题意:给你一个数组,和q次操作,单点修改或者查询一段区间的mex值(设区间内i的出现次数为ci,mex值为集合c与正整数集的补集的最小值)

    题解:带修莫队+简单暴力,稍微离散一下,因为ci最多有根号n种,复杂度O(n^(5/3)+n根号n)(代码巨丑无比)

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x=0;char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x;
    }
    struct xun{
        int l,r,t,id;
    }q[100005];
    int n,m,c[100005],be[100005],cnt1,cnt2=1,xiu[3][100005],sum[200005],ans[100005],ansum[100005],nnum[200005],anum[200005],cnu;
    bool cmp(xun a,xun b){return be[a.l]==be[b.l]?(be[a.r]==be[b.r]?a.t<b.t:a.r<b.r):a.l<b.l;}
    void rev(int x,int add)
    {
        ansum[sum[x]]--;
        sum[x]+=add;
        ansum[sum[x]]++;
    }
    void rev1(int x,int l,int r)
    {
        int a=c[xiu[0][x]],b=xiu[1][x];xiu[2][x]=a;
        c[xiu[0][x]]=b;
        if(xiu[0][x]>=l&&xiu[0][x]<=r)
        {
            ansum[sum[a]]--;ansum[--sum[a]]++;
            ansum[sum[b]]--;ansum[++sum[b]]++;
        }
    }
    void rev2(int x,int l,int r)
    {
        int a=c[xiu[0][x]],b=xiu[2][x];
        c[xiu[0][x]]=b;
        if(xiu[0][x]>=l&&xiu[0][x]<=r)
        {
            ansum[sum[a]]--;ansum[--sum[a]]++;
            ansum[sum[b]]--;ansum[++sum[b]]++;
        }
    }
    bool check(int x,int s)
    {
        if(nnum[x]<c[s]) return 1;
        else return 0;
    }
    bool check2(int x,int s)
    {
        if(nnum[x]<xiu[1][s]) return 1;
        else return 0;
    }
    int main()
    {
        int l,r,now=0,mid;
        n=read();m=read();
        int ttt=pow(n,2.0/3.0);
        for(int i=1;i<=n;i++) c[i]=read(),be[i]=i/ttt,nnum[++cnu]=c[i];
        for(int i=1,s;i<=m;i++)
        {
            s=read();
            if(s==1) q[++cnt1].l=read(),q[cnt1].r=read(),q[cnt1].t=cnt2,q[cnt1].id=cnt1;
            else xiu[0][++cnt2]=read(),xiu[1][cnt2]=read(),nnum[++cnu]=xiu[1][cnt2];
        }
        sort(nnum+1,nnum+cnu+1);
        for(int i=1,mmax=-1;i<=cnu;i++)
        {
            if(nnum[i]>mmax) mmax=nnum[i],now++;
            anum[i]=now;
        }
        for(int i=1,mid;i<=cnu;i++)
        {
            l=1,r=cnu;
            if(i<=n)
            {
            while(l<r)
            {
                mid=l+r>>1;
                if(check(mid,i)) l=mid+1;
                else r=mid;
            }
            c[i]=anum[l];
            }
            else
            {
            while(l<r)
            {
                mid=l+r>>1;
                if(check2(mid,i-n+1)) l=mid+1;
                else r=mid;
            }
            xiu[1][i-n+1]=anum[l];
            }
        }
        sort(q+1,q+1+cnt1,cmp);
        l=1;r=0;now=1;
        for(int i=1;i<=cnt1;i++)
        {
            while(r<q[i].r) rev(c[++r],1);
            while(l>q[i].l) rev(c[--l],1);
            while(l<q[i].l) rev(c[l++],-1);
            while(r>q[i].r) rev(c[r--],-1);
            while(now<q[i].t) rev1(++now,l,r);while(now>q[i].t) rev2(now--,l,r);
            for(int j=1;j<=200000;j++){if(!ansum[j]){ans[q[i].id]=j;break;}}
        }
        for(int i=1;i<=cnt1;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    idea 设置默认的maven
    IDEA中Tomcat部署时war和war exploded区别
    所谓的SaaS服务到底是什么?
    java8 Lambda表达式
    java8 :: 用法 (JDK8 双冒号用法)
    idea 本地调试,修改代码,代码自动生效
    nacos配置中心demo
    Logparser 的用法
    android软键盘的一些控制 转来的,格式有点乱
    TranslateAnimation 使用详解
  • 原文地址:https://www.cnblogs.com/zzpcd/p/8478032.html
Copyright © 2020-2023  润新知