2 条题解

  • 14
    @ 2025-3-4 9:10:32

    是这样的

    首先,只要你有正常人类所具备的思考能力,就可以想到

    ans=max{a[i]+a[i+1]}

    (不细说下标了,就是两个相邻的)

    但是!! 如果你就这样交上去的话,只会的到54pts(真可悲)

    所以我们思考一下:

    对于每一个小球,若令其发挥最大贡献,则其最多只能出现n2 \left \lfloor \frac{n}{2} \right \rfloor

    因为相邻两个小猴不能拥有同一种球,同时考虑到会出现奇数个小猴,所以下取整

    而所有小猴所需球的个数是i=1na[i] \sum_{i=1}^{n}a[i]

    所以ans下限至少也应该是$ \left \lceil \frac{\sum_{i=1}^{n}a[i]}{\left \lfloor \frac{n}{2} \right \rfloor} \right \rceil $

    为什么最后还要上取整我不说了,相信聪明的你一定能想明白

    最后的最后,不要忘记:

    只有一个小猴的时候特判一下!!!

    (不特判你将仍旧可以拿到100pts的好成绩)

    最后附上code:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    inline int read(){
    	int x=0,f=1;
    	char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')f=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return x*f; 
    }
    inline void write(int x){
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    const int N=114514;
    int n;
    int sum;
    int a[N];
    int ans=-2e9;
    int getup(int x,int y){
    	return (x+y-1)/y;
    }
    signed main(){
    	n=read();
    	for(int i=1;i<=n;i++){
    		a[i]=read();
    		sum+=a[i];
    		a[i+n]=a[i]; 
    	}
    	if(n==1){
    		write(a[1]);
    		return 0;
    	}
    	for(int i=1;i<n;i++)ans=max(ans,a[i]+a[i+1]);
    	ans=max(ans,getup(sum,n/2));
    	write(ans);
    	return 0;
    }
    
  • 1
    @ 2025-3-4 11:40:19

    首先我们想一个比较不一定对的dp

    dpidp_i 为前 ii 个数需要的最少的小球球

    首先我们显然可以想到第 ii 个人用的球不能用 i1i-1 的,但是可以用 i2i-2 个人的

    首先想到第 i1i-1 个人可能需要新加一些小球

    所以我们设 nw=dpi1dpi2nw=dp_{i-1}-dp_{i-2} 为前 i1i-1i2i-2 个人新增的多少个小球

    然后我们还可以处理出来第 i1i-1 个人用了多少个老球:used=ai1nwused=a_{i-1}-nw

    所以我们就可以算出来第 ii 个我现在能用多少个了can=dpi2usedcan=dp_{i-2}-used

    所以说如果 canaican ≥ a_idpi=dpi1dp_i=dp_{i-1}

    否则 dpi=dpi1+(aican)dp_i=dp_{i-1}+(a_i-can)

    但是此时我们算出来的答案可能不对

    我们换一个思路

    对于每一个小球,最多能发给 n/2n/2 个人

    所以说另一个最小可能小球数就是

    $$\left \lceil \frac{\sum_{i=1}^{n} a_i} {\left \lfloor \frac{n}{2} \right \rfloor } \right \rceil $$

    所以就过了

    #include<iostream>
    #include<cstdio>
    #define N 20005
    using namespace std;
    bool Test_MLE_start;
    int T=1,n,sum=0;
    int x[N],dp[N];
    bool Test_MLE_end;
    inline int reads(){
    	char c=getchar();
    	int sum=0,f=1;
    	while(!isdigit(c)){
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(isdigit(c)){
    		sum=(sum<<3)+(sum<<1)+(c-'0');
    		c=getchar();
    	}
    	return sum*f;
    }
    inline void files(){
    	freopen("std.in","r",stdin);
    	freopen("std.out","w",stdout);
    }
    signed main(){
    //	printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0);
    //	files();
    //	T=reads();
    	while(T--){
    		n=reads();
    		for(int i=1;i<=n;i++) x[i]=reads();
    		dp[1]=x[1],dp[2]=x[1]+x[2];
    		sum=dp[2];
    		for(int i=3;i<=n;i++){
    			sum+=a[i];
    			int nw=dp[i-1]-dp[i-2],used_old=x[i-1]-nw,can_use_old=dp[i-2]-used_old;
    			if(can_use_old>=x[i]) dp[i]=dp[i-1];
    			else dp[i]=dp[i-1]+(x[i]-can_use_old);
    		}
    		int t=n/2;
    		dp[n]=max(dp[n],(sum+t-1)/t);
    		printf("%d\n",dp[n]);
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    55
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    (无)
    递交数
    31
    已通过
    9
    上传者