比赛地址
A.Most Unstable Array
思路:显然 0 m 0 这样放是最大的
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,m;
int main() {
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>n>>m;
if(n==1)cout<<0<<endl;
else {
if(n==2){
cout<<m<<'\n';
}else cout<<2*m<<'\n';
}
}
return 0;
}
B.Two Arrays And Swaps
思路:把a,b排序,显然 最大的值必然是a的一个后缀 加上b的一个后缀,枚举即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,k,a[N],b[N];
int s[N],q[N];
int main() {
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int j=1;j<=n;j++){
cin>>b[j];
}
sort(a+1,a+1+n);
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i],q[i]=q[i-1]+b[i];
int ans=s[n];
for(int i=1;i<=k;i++){
ans=max(ans,s[n]-s[i]+q[n]-q[n-i]);
}
cout<<ans<<'\n';
}
return 0;
}
C.Board Moves
思路:
首先考虑一下暴力的代码:
int dx=(n+1)/2;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x=abs(i-dx),y=abs(j-dx);
ans+=x+y-min(x,y);
}
}
那么观察这个式子,我们可以通过枚举x,将y进行分段 [ 1 , x ] , [ x + 1 , n / 2 ] [1,x],[x+1,n/2] [1,x],[x+1,n/2]进行求和即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n;
int main() {
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>n;
LL ans=0;
if(n==1){
cout<<0<<'\n';
continue;
}
for(int i=1;i<=n/2;i++){
int x=(n+1)/2-i;
LL cnt=1ll*(1+n/2)*(n/2)/2;
cnt-=1ll*(n/2-x)*x+1ll*(1+x)*x/2;
ans+=2*cnt;
ans+=1ll*x*n;
}
ans=ans*2+1ll*(1+n/2)*(n/2);
cout<<ans<<'\n';
}
return 0;
}
D.Constructing the Array
思路:set模拟题意即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,a[N];
struct uzi{
int l,r,len;
bool operator < (const uzi & t)const{
if(len==t.len)return l<t.l;
return len>t.len;
}
};
set<uzi>s;
int ans[N];
int main() {
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>n;s.clear();s.insert({1,n,n});
for(int i=1;i<=n;i++){
auto x=*s.begin();
int l1,r1,l2,r2;
//cout<<x.l<<' '<<x.r<< ' '<<x.len<<endl;
if(x.len&1){
ans[(x.r+x.l)/2]=i;
l1=x.l,r1=(x.r+x.l)/2-1;
l2=(x.r+x.l)/2+1,r2=x.r;
}else{
ans[(x.r+x.l-1)/2]=i;
l1=x.l,r1=(x.r+x.l-1)/2-1;
l2=(x.r+x.l-1)/2+1,r2=x.r;
}
s.erase(x);
if(l1<=r1)s.insert({l1,r1,r1-l1+1});
if(l2<=r2)s.insert({l2,r2,r2-l2+1});
}
for(int i=1;i<=n;i++)cout<<ans[i]<<' ';cout<<'\n';
}
return 0;
}
E.K-periodic Garland
思路:显然要将n个位置按模k的结果分成k组进行分别判断。
每一组dp计算将这一组变成合法的最小操作数即可。
d
p
i
dp_i
dpi表示1-i的合法最少操作,那么根据第i个跟第i-1个是否连续可以推出转移方程:
1.连续
d
p
i
=
m
i
n
(
d
p
i
−
1
,
i
)
dp_i=min(dp_{i-1},i)
dpi=min(dpi−1,i)
2.不连续
d
p
i
=
m
i
n
(
d
p
i
−
1
+
a
i
−
a
i
−
1
−
1
,
i
)
dp_i=min(dp_{i-1}+a_i-a_{i-1}-1,i)
dpi=min(dpi−1+ai−ai−1−1,i)
然后在每个i处对答案进行更新即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,k,f[N];
char a[N];
vector<int>v;
int main() {
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>n>>k>>a+1;
int ans=1e9,cnt=0;
for(int i=1;i<=n;i++){
cnt+=(a[i]=='1');
}
ans=cnt;
for(int i=1;i<=k;i++){
int now=1;v.clear();
for(int j=i;j<=n;j+=k,now++){
if(a[j]=='1')v.pb(now);
}
if(!v.size())continue;
for(int j=0;j<=(int)v.size();j++)f[j]=1e9;
f[0]=0;
for(int j=1;j< (int)v.size();j++){
if(v[j]==v[j-1]+1){
f[j]=min(f[j-1],j);
}else{
f[j]=min(f[j-1]+(v[j]-v[j-1]-1),j);
}
ans=min(ans,cnt-(int)v.size()+f[j]+((int)v.size()-1-j));
}
ans=min(ans,cnt-(int)v.size()+f[(int)v.size()-1]);
}
cout<<max(0,ans)<<'\n';
}
return 0;
}
F.Decreasing Heights
思路:显然路径中至少有一个位置的高度是不变的,否则必然不是最优解。
那么枚举高度不变的位置,dp计算从这个点出发,走到左上和右下的最少操作数即可。
ps:当起点的高度确定的时候,起点能到达的每个点的高度都是确定的。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,m,vis[111][111];
LL a[111][111],dp[111][111];
LL b[111][111];
int main() {
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>n>>m;LL ans=LLONG_MAX;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)cin>>a[i][j];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int x=1;x<=n;x++){
for(int y=1;y<=m;y++)dp[x][y]=1e18;
}
b[i][j]=a[i][j];
dp[i][j]=0;
for(int x=i;x>=1;x--){
for(int y=j;y>=1;y--){
if(x==i&&y==j)continue;
if(x+1<=i ){
b[x][y]=b[x+1][y]-1;
if(a[x][y]>=b[x][y])
dp[x][y]=min(dp[x][y],dp[x+1][y]+abs(a[x][y]-b[x][y]));
}
if(y+1<=j){
b[x][y]=b[x][y+1]-1;
if(a[x][y]>=b[x][y])
dp[x][y]=min(dp[x][y],dp[x][y+1]+abs(a[x][y]-b[x][y]));
}
}
}
for(int x=i;x<=n;x++){
for(int y=j;y<=m;y++){
if(x==i&&y==j)continue;
if(x-1>=i){
b[x][y]=b[x-1][y]+1;
if(a[x][y]>=b[x][y])
dp[x][y]=min(dp[x][y],dp[x-1][y]+abs(a[x][y]-b[x][y]));
}
if(y-1>=j){
b[x][y]=b[x][y-1]+1;
if(a[x][y]>=b[x][y])
dp[x][y]=min(dp[x][y],dp[x][y-1]+abs(a[x][y]-b[x][y]));
}
}
}
//cout<<i<<' '<<j<< ' '<<dp[1][1]<<' '<<dp[n][m]<<endl;
ans=min(ans,dp[1][1]+dp[n][m]);
}
}
cout<<ans<<'\n';
}
return 0;
}