【UVA1335】Beijing Guards

探讨了如何通过分配不同类型奖项来激励北京城墙上的守卫,确保相邻守卫获得的奖项不同,以维持他们的积极性。使用二分查找算法确定所需奖项种类的最小数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面

  Beijing was once surrounded by four rings of city walls: the Forbidden City Wall, the Imperial City Wall, the Inner City Wall, and finally the Outer City Wall. Most of these walls were demolished in the 50s and 60s to make way for roads. The walls were protected by guard towers, and there was a guard living in each tower. The wall can be considered to be a large ring, where every guard tower has exaetly two neighbors.
  The guard had to keep an eye on his section of the wall all day, so he had to stay in the tower.
  This is a very boring job, thus it is important to keep the guards motivated. The best way to motivate a guard is to give him lots of awards. There are several different types of awards that can be given: the Distinguished Service Award, the Nicest Uniform Award, the Master Guard Award, the Superior Eyesight Award, etc. The Central Department of City Guards determined how many awards have to be given to each of the guards. An award can be given to more than one guard. However, you have to pay attention to one thing: you should not give the same award to two neighbors, since a guard cannot be proud of his award if his neighbor already has this award. The task is to write a program that determines how many different types of awards are required to keep all the guards motivated.

题意

  有n个人,每个人想要有ri种不同的物品,相邻的两个人拥有的物品种类不能相同(ii+1相邻,n和1相邻),求至少需要多少种物品才能满足条件

解法

二分:
  通过手画一些简单的例子可以发现,答案和n的奇偶性有关:
  如果n为偶数,那么ans=maxansri+ri+1,我们从第一位开始放,第一位和第二位显然要不同,所以需要r1+r2种物品,然后看第三位,如果r3r1,那么直接将第一位的物品种类放在第三位即可,否则在第三位就还需要多r3r1种,即答案更新为r2+r3(因为n为偶数,所以奇数位肯定不会和1相邻),以此类推,在第四位则比较和第二位的大小,第五位则比较和第三位的大小……
  如果n为奇数,这种情况就比较麻烦,因为最后一个奇数位会和1相邻,而根据上面的做法,奇数位至少有min{ri|i=2k+1k0n1/2}种物品是相同的,所以不能按上面的方法做。
  显然,如果我们将物品种类分为1r1=xansr1+1ans=y两个部分,第一位选取的物品全部在前半部分,那么我们的目标就是要最后一位选取物品全在后半部分
  直接得出ans很难,于是考虑二分,上界R=ni=1ri,下界L=max{ri+ri+1},rn+1=r1
  对于中点mid,设pi表示第i位在前半部分选取了多少种物品,qi表示第i位在后半部分选取了多少种物品(i1
  如果i为奇数,那么尽量在后半部分选,即qi=minyqi1r[i]pi=riqi
  否则,尽量在前半部分选,即pi=minxpi1riqi=ripi
  最后的判断依据就是pn是否为0

复杂度

O(nlogn

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#define Lint long long int
using namespace std;
const int MAXN=100010;
int p[MAXN],q[MAXN];
int r[MAXN];
int n;
bool check(int lim)
{
    int x=r[1],y=lim-r[1];
    p[1]=x,q[1]=0;
    for(int i=2;i<=n;i++)
        if( i%2 )
        {
            q[i]=min( y-q[i-1],r[i] );
            p[i]=r[i]-q[i];
        }
        else
        {
            p[i]=min( x-p[i-1],r[i] );
            q[i]=r[i]-p[i];
        }
    return !p[n];
}
int main()
{
    int L,R;
    while( scanf("%d",&n) && n )
    {
        for(int i=1;i<=n;i++)   scanf("%d",&r[i]);
        if( n==1 )   { printf("%d\n",r[n]);continue ; }
        L=0,R=0;
        r[n+1]=r[1];
        for(int i=1;i<=n;i++)   L=max( L,r[i]+r[i+1] );
        if( n%2 )
        {
            for(int i=1;i<=n;i++)   R+=r[i];
            while( L<=R )
            {
                int mid=(L+R)/2;
                if( check( mid ) )   R=mid-1;
                else   L=mid+1;
            }
        }
        printf("%d\n",L);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值