zoukankan      html  css  js  c++  java
  • gym 101911

    A. Coffee Break

    题意:每天有m小时,你喝咖啡需要花一小时,你想在n个时刻都喝过一次咖啡,老板规定连续喝咖啡的间隔必须是d以上,求最少需要多少天才能喝够n次咖啡,并输出每个时刻第几天喝。

    题解:map+优先队列,用map将愿意喝咖啡的时间喝在第几天喝咖啡映射起来,优先队列遍历每个时刻和上一次喝的时间间隔是否大于d,若大于d,表示可以同一天喝,否则就在下一天喝

    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<string.h>
    #include<vector>
    #include<utility>
    #include<map>
    #include<queue>
    using namespace std;
    map<int,int>m;
    priority_queue<int,vector<int>,greater<int> >p;
    int a[200005],b[200005];
    int main()
    {
        int n,t,d;
        scanf("%d%d%d",&n,&t,&d);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&b[i]);
            a[i]=b[i];
        }
        sort(a,a+n);
        m[a[0]]=1;//最小的时间点一定是第一天就可以喝
        p.push(a[0]);
        int cnt=1;
        for(int i=1;i<n;i++)
        {
            int now=p.top();
            if(a[i]-now>d)
            {
                m[a[i]]=m[now];//可以同一天喝
                p.pop();
            }
            else
                m[a[i]]=++cnt;//只能下一天喝
            p.push(a[i]);
        }
        printf("%d
    ",cnt);
        for(int i=0;i<n;i++)
        {
            if(i==0)
                printf("%d",m[b[i]]);
            else
                printf(" %d",m[b[i]]);
        }
        printf("
    ");
        return 0;
    }

    B

    题意:有nn个上升气流带,在这里飞行不会下降,否则每前进一会下降1格。求出从某个起点能飞的尽可能远的距离。

    题解:起点肯定是某个区间的起点,但枚举起点显然会超时,但显然从当前起点向前可以穿过的区间数和其花费是单调递增,所以处理出前缀和后枚举起点二分终点即可获得答案

    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<string.h>
    #include<vector>
    #include<utility>
    #include<map>
    #include<queue>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    ll start[200005],sum[200005],len[200005],len2[200005];
    int main()
    {
        ll n,h;
        scanf("%lld%lld",&n,&h);
        for(int i=1;i<=n;i++)
        {
            ll l,r;
            scanf("%lld%lld",&l,&r);
            start[i]=l;
            len[i]=r-l;//区间长度
        }
        for(int i=1;i<=n-1;i++)
            len2[i]=start[i+1]-(start[i]+len[i]);//两个区间之间的间隔长度
    
        len2[n]=mx;
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+len2[i];//前缀和
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ll l=i,r=n,mid,pos;
            while(l<=r)
            {
                mid=l+(r-l)/2;
                if(sum[mid]-sum[i-1]>=h)
                {
                    pos=mid;
                    r=mid-1;
                }
                else
                    l=mid+1;
            }
            ll hh=h-(sum[pos-1]-sum[i-1]);//最后一段飘的距离
            ans=max(ans,start[pos]-start[i]+len[pos]+hh);
        }
        printf("%lld
    ",ans);
        return 0;
    
    }

    C. Bacteria

    题意:碗里有n个细菌,只有重量相同的细菌才可以合并在一起,合并后的细菌为两个细菌之后,为了把碗里的所有细菌合并成一个细菌,问最少还要向碗里增加几个细菌?若最后不能合并成一个细菌,输出-1,否则输出最少要加入的细菌个数

    题解:优先队列逐个处理即可

    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    ll gcd(ll a, ll b)//最大公约数
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    ll lcm(ll a, ll b)//最小公倍数
    {
        return a / gcd(a, b) * b;
    }
    priority_queue<ll,vector<ll>,greater<ll> > p;
    int main()
    {
        ll n;
        scanf("%lld",&n);
        for(int i=0;i<n;i++)
        {
            ll temp;
            scanf("%lld",&temp);
            p.push(temp);
        }
        ll flag=0,cnt=0;
        while(p.size()!=1)
        {
            ll now=p.top();
            p.pop();
            if(p.size()==1)
            {
                if(lcm(now,p.top())!=p.top())
                {
                    flag=1;
                    break;
                }
            }
            if(now==p.top())
            {
                now=now+p.top();
                p.pop();
                p.push(now);
            }
            else
            {
                cnt++;
                now=now*2;
                p.push(now);
            }
        }
        if(flag==1)
            printf("-1
    ");
        else
            printf("%lld
    ",cnt);
        return 0;
    }

    D、

    题意:给你nn个数,你要给出不同的组合(a,b)(a,b)使得ab=A[i]ab=A[i],不能重复,但是(a,b)(a,b)和(b,a)(b,a)不同

    题解:按照输入顺序枚举每一个数的因子,枚举到一个因子num[i]之后就退出,同时用vis[]反向标记一下这个数,下一次再次遇到这个数,就从上一次的因子num[i]+1继续枚举

    用pair数组保存每一个数的一对因子

    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<string.h>
    #include<vector>
    #include<utility>
    #include<map>
    using namespace std;
    int vis[10000005],num[10000005];//vis反向标记,用num保存一个因子
    pair<int,int>p[200005];
    int a[200005];
    int n;
    int solve()
    {
        for(int i=0;i<n;i++)
        {
            if(vis[a[i]]==1)
            {
                vis[a[i]]=0;
                p[i].first=a[i]/num[a[i]];
                p[i].second=num[a[i]];
                continue;
            }
            int flag=0;
            for(int j=num[a[i]]+1;j<=sqrt(a[i]);j++)//对于每个数从最小的因子开始找,找到一对就退出,下一次再次遇到这个数就从num[a[i]]+1开始找因子
            {
                if(a[i]%j==0)
                {
                    flag=1;
                    num[a[i]]=j;//num只存一个因子即可
                    if(a[i]/j!=j)
                        vis[a[i]]=1;//反向标记,例如第一次找到一组[1,3],用vis标记[3,1]的存在
                    p[i].first=j;
                    p[i].second=a[i]/j;
                    break;//对于每个数,找到一对因子就退出
                }
            }
            if(flag==0)
                return 0;
        }
    
        return 1;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            num[a[i]]=0;//初始化a[i]的因子为0
        }
        if(solve())
        {
            printf("YES
    ");
            for(int i=0;i<n;i++)
                printf("%d %d
    ",p[i].first,p[i].second );
        }
        else
            printf("NO
    ");
    }

    E

    题意:有n块木板初始有颜色ai...an,刷m次漆,每次刷漆选择一种颜色从当前颜色的最左端刷到当前颜色的最右端,问经过m次刷漆以后最终木板的颜色序列

    思路:用set维护各颜色拥有的木板下标,每次涂色直接取set.begin和set.rbegin进行刷漆,此外当一种颜色刷过以后,它所刷过的区间就不再需要遍历,将其左右边界流在set里即可,下次再遍历到这些点直接跳过该区间

    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<string.h>
    #include<vector>
    #include<utility>
    #include<map>
    #include<queue>
    #include<set>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    int a[300005],vis[300005];
    set<int>p[300005];
    int main()
    {
        int n,m,x;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            p[a[i]].insert(i);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&x);
            if(p[x].size()<2||vis[x])
            {
                vis[x]=1;
                continue;
            }
            int l=*(p[x].begin());//*注意优先级
            int r=*(p[x].rbegin());
            for(int j=l+1;j<=r-1;j++)//保留第一个和最后一个位置,中间的位置全部删除
            {       
                p[a[j]].erase(j);
                if(vis[a[j]]==1&&p[a[j]].size()>=1)//遍历过的值直接跳到相应位置开始删除位置
                {
                    j=*(p[a[j]].begin());
                    p[a[j]].erase(j);
                }
            }
            vis[x]=1;
        }   
        for(int i=0;i<300005;i++)
        {
            if(vis[i]==1&&p[i].size()>=2)//填充中间位置的数
            {
                int l=*(p[i].begin());
                int r=*(p[i].rbegin());
                for(int j=l;j<=r;j++)
                    a[j]=i;
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(i==1)
                printf("%d",a[i]);
            else
                printf(" %d",a[i]);
        }
        printf("
    ");
        return 0;
    }

    F. Tickets

    题意:有n次询问每次询问给一个数x,且x自动补全六位ABCDEF(可以有前导零),一个数的不幸运值=abs((D+E+F)-(A+B+C)),求出每个在这个数之前比自己不幸运值低的数的个数

    题解:提前预处理所有数的不幸运值,然后统计比这个不幸运值低的数的个数

    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    int a[1000005],cnt[300];
    ll gcd(ll a, ll b)//最大公约数
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    int num(int i)
    {
        int x=0, y=0;
        int xx=0,yy=0;
        x=i%1000;
        y=i/1000;
        while(x)
        {
            int temp=x;
            x=x/10;
            xx=xx+temp%10;
        }
        while(y)
        {
            int temp=y;
            y=y/10;
            yy=yy+temp%10;
        }
        return abs(xx-yy);
    }
    
    int main()
    {
        int x;
        memset(cnt, 0, sizeof(cnt));
        for(int i=0; i<1000000; i++)
        {
            a[i] = 0;
            x = num(i);
            cnt[x]++;
            for(int j=0; j<x; j++)
            {
                a[i]+=cnt[j];
            }
        }
        int n;
        scanf("%d", &n);
        while(n--)
        {
            scanf("%d", &x);
            printf("%d
    ", a[x]);
        }
        return 0;
    }

    H. Theater Square

    题意:有一个矩形,挖掉一个小矩形之后用1*2的方块填充这个矩形,填充不完整的地方(会留有一些1*1)需要将1*2的方块打碎成两块用来填充,问打碎多少块1*2的方块

    模拟即可

    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    int a[1000005],cnt[300];
    ll gcd(ll a, ll b)//最大公约数
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    int num(int i)
    {
        int x=0, y=0;
        int xx=0,yy=0;
        x=i%1000;
        y=i/1000;
        while(x)
        {
            int temp=x;
            x=x/10;
            xx=xx+temp%10;
        }
        while(y)
        {
            int temp=y;
            y=y/10;
            yy=yy+temp%10;
        }
        return abs(xx-yy);
    }
    
    int main()
    {
        int x;
        memset(cnt, 0, sizeof(cnt));
        for(int i=0; i<1000000; i++)
        {
            a[i] = 0;
            x = num(i);
            cnt[x]++;
            for(int j=0; j<x; j++)
            {
                a[i]+=cnt[j];
            }
        }
        int n;
        scanf("%d", &n);
        while(n--)
        {
            scanf("%d", &x);
            printf("%d
    ", a[x]);
        }
        return 0;
    }

    I

    题意:对一组本来连续的数,现在缺失了几个,问你最少缺失了几个

    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    ll a[1005];
    int main()
    {
       ll n;
       scanf("%lld",&n);
       for(int i=0;i<n;i++)
        scanf("%lld",&a[i]);
        sort(a,a+n);
        int cnt=0;
        for(int i=1;i<n;i++)
            cnt=cnt+a[i]-a[i-1]-1;
        printf("%d
    ",cnt);
    }

    J

    题意:多少组w、h的比例满足x/y,要求w<=a&&h<=b

    题解:将x/y化成最简分数,答案就是min(a/x,b/y);

    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    
    ll gcd(ll a, ll b)//最大公约数
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    int main()
    {
       ll a,b,x,y,xx;
       scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
       xx=gcd(x,y);
       x=x/xx;
       y=y/xx;
       printf("%lld
    ",min(a/x,b/y));
    }

    K

    题意:可以将n个数进行区间分割要求每个区间的中位数>=m问最多可以分成多少个区间

    题解:先将所有数从小到大排序,找到第一个满足条件的中位数,之后的所有数都满足条件

    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    ll gcd(ll a, ll b)//最大公约数
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    ll lcm(ll a, ll b)//最小公倍数
    {
        return a / gcd(a, b) * b;
    }
    priority_queue<ll,vector<ll>,greater<ll> > p;
    int a[5005];
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        sort(a,a+n);
        int len=0,now=0,cnt=0;
        for(int i=0;i<n;i++)
        {
            if(a[i]>=m)
                break;
            len++;
        }
    
        for(int i=len;i<n;i++)
        {
            if(a[i]>=m&&len==now)
            {
                cnt++;
                cnt=cnt+n-(i+1);
                break;
            }
            else
                now++;
        }
        printf("%d
    ",cnt);
        return 0;
    }
  • 相关阅读:
    mybatis专题(一)-----入门、配置
    如何在抽象类中注入bean
    spring是如何解决循环依赖的?
    Java 程序员必须了解的计算机底层知识!
    数据库底层到底是怎么设计的?
    关于Rigidbody,Collider和CharacterController三者之间的关系和用法的总结
    泛型c#(深入理解c#)
    协程的NullReferenceException 错误
    进度条的制作unity
    Rigidbody.Is Kinematic和碰撞体
  • 原文地址:https://www.cnblogs.com/-citywall123/p/11337031.html
Copyright © 2011-2022 走看看