2021牛客多校第六场


题目链接

A Contracting Convex Hull

C Delete Edges

思路

就是要让三个点相加对n取模为0,找出所有满足的点,输出即可。证明略。

附上代码

#include <iostream>
#include <bits/stdc++.h>

#define inf 0x3f3f3f3f
#define mod 1000000007
#define lmax 1000
#define pi 3.141592653589793238462643383279
#define eps 1e-7

using namespace std;
typedef long long ll;
typedef double type;
int a[20000000][3];//数组开的一定要大一点,小了存不了,或者可以用vector

int main()
{
    int n;
    scanf("%d",&n);
    int kx=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            int k=(n-i-j)%n;//保证(i+j+k)%n==0
            if(k<=0)k+=n;
            if(k<=j)continue;
            a[kx][0]=i;
            a[kx][1]=j;
            a[kx][2]=k;
            kx++;
        }
    }
    printf("%d\n",kx);
    for(int i=0;i<kx;i++)
    {
        printf("%d %d %d\n",a[i][0],a[i][1],a[i][2]);
    }
    return 0;
}

F Hamburger Steak

思路

首先我们需要保证所有锅的时间和大于等于所有汉堡排的时间和,以及耗时最长的汉堡排不会再同一时刻分到两个锅中。𝑇=max⁡{max⁡ a[i],(∑a[i])/𝑚)}。
然后在知道T的情况下,贪心地将每个锅的时间依次分配给每个汉堡排,当前这个锅没煎完的由下个锅煎完即可。

附上代码

#include <iostream>
#include <bits/stdc++.h>

#define inf 0x3f3f3f3f
#define mod 1000000007
#define lmax 1000
#define pi 3.141592653589793238462643383279
#define eps 1e-7

using namespace std;
typedef long long ll;
typedef double type;
ll a[100009];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    ll k=0,maxn=0,sum=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        maxn=max(maxn,a[i]);
        sum+=a[i];
    }
    k=sum/m;
    if(sum%m!=0)
        k++;
    maxn=max(maxn,k);//maxn表示每个盘子可以使用的最长的时间
    ll nw=1;//表示盘子是第几个
    long long lef=maxn;//表示每个盘子剩余的时间
    for (int i=1; i<=n; i++)
    {
        if (lef>=a[i])//当前盘子可以煎完这个汉堡
        {
            printf("1 %lld %lld %lld\n",nw,maxn-lef,maxn-lef+a[i]);//第几个盘子,煎汉堡初始时间,煎汉堡结束时间
            lef-=a[i];//更新盘子剩余时间
            if (!lef)//盘子剩余时间为零时,更新至下一个盘子
            {
                lef=maxn;
                nw++;
            }
        }
        else//当前盘子无法煎完这个汉堡,先用下一个盘子的前几分钟煎,再用当前盘子的后几分钟煎,然后更新到下一个盘子
        {
            printf("2 %lld 0 %lld %lld %lld %lld\n",nw+1,a[i]-lef,nw,maxn-lef,maxn);//下一盘子数,0,煎完的时间,当前盘子数,初始时间,结束时间
            nw++;//更新到新的盘子,并更新其剩余时间
            lef=maxn-(a[i]-lef);
        }
    }

    return 0;
}

H Hopping Rabbit

I Intervals on the Ring

思路

这道题题意就是给了你一些区间,先求出这些区间的并集,让你构造一些区间,使得你构造区间的交集等于题目中给出区间的并集。需要注意的就是给出的序列是一个环状序列,就是n和1是相连的,比如序列长度为10,区间为[8,2],意思就是8,9,10,1,2。
我们可以先将选中的元素标记出来,看看有几个连续的区间,需要注意的是当n和1都取到的时候,需要将第一个和最后一个区间合并。

附上代码

#include<iostream>
#include <bits/stdc++.h>
 
using namespace std;
 
int a[1005];//标记并集中是否包括某个元素
int k[1005];//存储连续被标记的区间,从0开始,两个数表示一个区间
 
int main()
{
    int t,n,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int l,r;
        memset(a,0,sizeof(a));
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&l,&r);
            if(l<=r)//开始标记
                for(int j=l;j<=r;j++)
                {
                    a[j]=1;
                }
            else
            {
                for(int j=1;j<=r;j++)
                {
                    a[j]=1;
                }
                for(int j=l;j<=n;j++)
                {
                    a[j]=1;
                }
            }
        }
        int num=0;//表示区间的数量
        int i;//表示a数组的下标,只需要遍历一遍即可
        int kx=0;//表示k数组的下标
        for(i=1;i<=n;)//求得连续区间,并将区间信息存在k数组中
        {
            if(a[i]==0)
            {
                i++;
                continue;
            }
            bool bol=true;
            while(1)
            {
                if(bol)
                {
                    bol=false;
                    k[kx]=i;
                    kx++;
                }
                i++;
                if(a[i]==0)
                {
                    k[kx]=i-1;
                    kx++;
                    num++;
                    break;
                }
            }
        }
        bool biao=true;//如果最后一个和第一个都在并集中,那么就将两者合并为一个区间
        if(a[1]==1&&a[n]==1&&num>1)
        {
            num--;
            biao=false;
        }
        if(num>2)//这里我分为了三种情况,其实分两种情况就行
        {
            if(biao)
            {
                printf("%d\n",kx/2);
                for(int kk=0;kk<kx-1;kk+=2)
                {
                    printf("%d %d\n",k[kk],k[(kx-1+kk)%kx]);
                }
            }
            else
            {
                kx-=2;
                printf("%d\n",kx/2);
                printf("%d %d\n",k[kx],k[kx-1]);
                for(int kk=2;kk<kx-1;kk+=2)
                {
                    printf("%d %d\n",k[kk],k[(kx-1+kk)%kx]);
                }
            }
        }
        else if(num==2)
        {
            if(biao)
            {
                printf("2\n%d %d\n%d %d\n",k[2],k[1],k[0],k[3]);
            }
            else
            {
                printf("2\n%d %d\n%d %d\n",k[2],k[1],k[4],k[3]);
            }
        }
        else if(num==1)
        {
            if(biao)
            {
                printf("1\n%d %d\n",k[0],k[1]);
            }
            else
            {
                printf("1\n%d %d\n",k[2],k[1]);
            }
        }
        else//我分析了一下,因为m不为0,因此这种情况应该不会出现,不过还是写上比较好
        {
            printf("-1\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值