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=1n∣ai−ai+1∣+∣bi−bi+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=(2⋅v) 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