Educational Codeforces Round 148 (Rated for Div. 2)

Problem - D2 - Codeforces

思路:

  1. 首先,观察到,一个点修改奇数次,一定是增大。修改偶数次,一定是会减小,且最少也是-1.
  2. 注意到只要操作过偶数次,这个值已经有所减少,那么你后面加一次也不能达到最大效益了,即如果要使一个数尽可能被加大,那么只加一次是最优的(比如加k,如果第一次加是+k,如果第三次才加,至多也只是+k-1)
  3. 我们如何最大化那个最小的数?显然是把最大数值加给最小的,次大给次小,所以先给数值排序(小到大)
  4. 分析n与k的关系
    1. 如果k<=n,显然可以每个数都只操作一次
    2. 如果k>n,我们还是希望每个数都能加上k,k-1....k-n+1这前n大的数。
      1. 当然,前提是你要保证他们都是加的,即每个数各自加上上述的数时必须被操作了偶数次(保证是红色)。所以(k-n)mod 2=0即可n个数都加上,如果mod 2=1,则只有前n-1个数可以
      2. 也就是说,我们现在就剩如何分配剩余的(k-n)/2对-1了(这里的-1对数举(k-n)mod 2=0时的情况),显然,-1可以先分配给那些大于最小值的数承担。如果承担完了还有剩,那么接下来就是n个数一起减少(最后记得向上取整)
  5. 我们每次这么寻找修改后的最小值呢,发现a[i]如果被修改,那么他的新值就是a[i]'=a[i]-i+1+k。因为一次询问k是固定的,我们可以维护b[i]=a[i]-i+1数组的最小值,显然后面只需比较该最小值+k即可。
#include <bits/stdc++.h>
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long
const ll llINF = 0x3f3f3f3f3f3f3f3f;//ll型的llINF

const int N = 3e5 + 10;
int a[N],min1[N],b[N];
void mysolve()
{
	int n,q;
	cin>>n>>q;
	for(int i=1; i<=n; ++i)cin>>a[i];
	sort(a+1,a+1+n);
	min1[1]=b[1]=a[1];
	a[n+1]=llINF;
	int sum=b[1];
	for(int i=2; i<=n; ++i)b[i]=a[i]-i+1,min1[i]=min(b[i],min1[i-1]),sum+=b[i];//min维护b数组最小值,sum记录全部修改后的数的值的和
	int k;
	while(q--)
		{
			cin>>k;
			if(n==1)//因为我们处理时常常需要至少2个位置,所以1特判处理比较容易
				{
					cout<<a[1]-k/2+(k&1?k:0)<<" ";
					continue;
				}
			if(k<=n)cout<<min(min1[k]+k,a[k+1])<<" ";//k<=n答案就是修改了的最小值+k与未修改的最小值(显然a[k+1]~a[n]最小值是a[k+1],排序了)
			else
				{
					int tmp=k-n+1;
					if((k-n)%2==0)
						{
							tmp--;
							tmp/=2;//看成一对数(-1)处理
						int res=sum+n*k-n*(min1[n]+k);//n个数都有加k,他们的所以值和就是sum+n*k,他们的最小值就是min1[n]+k,我们把那些大的可以承担的数先去抵消-1
							tmp=max(tmp-res,0ll);
							cout<<min1[n]+k-(tmp+n-1)/n<<" ";//向上取整
						}
					else
						{
							int minn=min(min1[n-1]+k,a[n]);
							int res=sum+n-1+(n-1)*k-n*minn;//只有n-1个数有+k
							tmp/=2;
							tmp=max(tmp-res,0ll);
							cout<<minn-(tmp+n-1)/n<<" ";
						}
				}
		}
}

int32_t main()
{
	std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll t=1;
	//cin >> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值