Educational Codeforces Round 126 (Rated for Div. 2)

A. Array Balancing

  • 题目大意
    给定两个长度为n的数组a和b,规定一次操作为交换 a i a_i ai b i b_i bi,问经过任意合法交换后, ∑ i = 1 n ∣ a i − a i + 1 ∣ + ∣ b i − b i + 1 ∣ \sum_{i=1}^{n}|a_i-a_{i+1}|+|b_i-b_{i+1}| i=1naiai+1+bibi+1最小值为多少?
  • 思路
    从头到尾模拟一遍每一个位置交换还是不交换就好了。
  • code
#include<bits/stdc++.h>
using namespace std;
#define N 30
int t,n;
long long a[N],b[N];

int main()
{
	cin>>t;
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		for(int i=1;i<=n;i++) scanf("%d",&b[i]);
		long long sum=0;
		for(int i=2;i<=n;i++) 
		{
			if(abs(a[i]-a[i-1])+abs(b[i]-b[i-1])>abs(b[i]-a[i-1])+abs(a[i]-b[i-1])) swap(a[i],b[i]);
			sum+=abs(a[i]-a[i-1])+abs(b[i]-b[i-1]);
			//cout<<a[i]<<' '<<b[i]<<endl;
		}
		cout<<sum<<endl;
	}

	return 0;
}

B. Getting Zero

  • 题目大意
    给定n个数 a 1... n a_{1...n} a1...n,你可以对这n个数进行两种操作:
    either set v = ( v + 1 )   m o d   32768 v=(v+1)\ mod\ 32768 v=(v+1) mod 32768
    or set v = ( 2 ⋅ v )   m o d   32768 v=(2⋅v)\ mod\ 32768 v=(2v) mod 32768
    输出每个数至少经过多少次操作被置为0。
  • 思路
    首先发现 32768 = 2 15 32768=2^{15} 32768=215,因此对于任何数来说只要乘15次2一定会变成32768的倍数,因而被置为0,因此,最多操作15次。
    其次,一定是先进行 + 1 +1 +1运算再进行 × 2 \times 2 ×2运算更优,证明: 2 ( v + 1 ) = 2 v + 2 2(v+1)=2v+2 2(v+1)=2v+2,即乘2之后想达到相同的效果就要进行更多的加操作。因此,可以试探先加1到15,然后再乘1到15次,选择出最小的操作次数即可。
  • code
#include<bits/stdc++.h>
using namespace std;
#define N 32770
#define mod 32768
int n,x;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		int ans=15,op=0;
		for(int j=0;j<=15;j++)
		{
			for(int k=0;k<=15;k++)
			{
				if(((x+j)<<k) % mod==0) ans=min(ans,j+k);
			}
		}
		cout<<ans<<' ';
	}
	return 0;
}

C. Water the Trees

  • 题目大意
    现在有n颗树,每棵树 i i i有一个高度 h i h_i hi,现在每天可以给最多一棵树浇水,若在奇数天浇水树就会长高1,若在偶数天浇水树就会长高2。
    问最少用多少天可以让所有的树长到相同的高度。
  • 思路
    一个思路是:可以二分答案为mid,然后奇数天为 c e i l ( m i d / 2 ) ceil(mid/2) ceil(mid/2),偶数天为 f l o o r ( m i d / 2 ) floor(mid/2) floor(mid/2)。然后check这个答案是否合法即可:首先贪心的使用偶数,然后剩下的用奇数天来填,要是能填够即说明这个答案合法。
  • code
#include<bits/stdc++.h>
using namespace std;
#define N 300005 
#define ll long long
ll t,n,a[N];
bool check(ll x, ll maxn)
{
	ll day1=(x+1)/2,day2=x/2;
	ll b=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i]>=maxn) continue;
		ll temp=maxn-a[i];
		if(temp/2<=day2) 
		{
			day2-=temp/2;
			b+=temp%2;
		}
		else 
		{
			temp-=day2*2;
			day2=0;
			b+=temp;	
		}
	}
	if(b<=day1) return true;
	else return false;
}
int main()
{
	cin>>t;
	while(t--)
	{
		scanf("%lld",&n);
		ll maxn=0;
		for(int i=1;i<=n;i++){scanf("%lld",&a[i]);maxn=max(maxn,a[i]);}
		ll l=0,r=n*maxn,ans=n*maxn;
		while(l<=r)
		{
			ll mid=(l+r)>>1;
			if(check(mid,maxn)) ans=min(mid,ans),r=mid-1;
			else l=mid+1;
		}
		l=0,r=n*maxn;
		while(l<=r)
		{
			ll mid=(l+r)>>1;
			if(check(mid,maxn+1)) ans=min(mid,ans),r=mid-1;
			else l=mid+1;
		}
		cout<<ans<<endl;
	}
	return 0;
}

D. Progressions Covering

  • 题目大意

  • 思路

  • code


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值